translate.c (e8325dc02d059685331d8607d5e620328bac594e) translate.c (0faef01b3989bb1fb6e0ed73ffa909e77b79f780)
1/*
2 SPARC translation
3
4 Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
5 Copyright (C) 2003-2005 Fabrice Bellard
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public

--- 24 unchanged lines hidden (view full) ---

33#include "asi.h"
34
35#define HELPER_H "helper.h"
36#include "exec/helper-info.c.inc"
37#undef HELPER_H
38
39#ifdef TARGET_SPARC64
40# define gen_helper_rdpsr(D, E) qemu_build_not_reached()
1/*
2 SPARC translation
3
4 Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at>
5 Copyright (C) 2003-2005 Fabrice Bellard
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public

--- 24 unchanged lines hidden (view full) ---

33#include "asi.h"
34
35#define HELPER_H "helper.h"
36#include "exec/helper-info.c.inc"
37#undef HELPER_H
38
39#ifdef TARGET_SPARC64
40# define gen_helper_rdpsr(D, E) qemu_build_not_reached()
41# define gen_helper_power_down(E) qemu_build_not_reached()
41#else
42#else
43# define gen_helper_clear_softint(E, S) qemu_build_not_reached()
42# define gen_helper_flushw(E) qemu_build_not_reached()
43# define gen_helper_rdccr(D, E) qemu_build_not_reached()
44# define gen_helper_rdcwp(D, E) qemu_build_not_reached()
44# define gen_helper_flushw(E) qemu_build_not_reached()
45# define gen_helper_rdccr(D, E) qemu_build_not_reached()
46# define gen_helper_rdcwp(D, E) qemu_build_not_reached()
47# define gen_helper_set_softint(E, S) qemu_build_not_reached()
45# define gen_helper_tick_get_count(D, E, T, C) qemu_build_not_reached()
48# define gen_helper_tick_get_count(D, E, T, C) qemu_build_not_reached()
49# define gen_helper_wrccr(E, S) qemu_build_not_reached()
50# define gen_helper_write_softint(E, S) qemu_build_not_reached()
46# define MAXTL_MASK 0
47#endif
48
49/* Dynamic PC, must exit to main loop. */
50#define DYNAMIC_PC 1
51/* Dynamic PC, one of two values according to jump_pc[T2]. */
52#define JUMP_PC 2
53/* Dynamic PC, may lookup next TB. */

--- 2807 unchanged lines hidden (view full) ---

2861#define TRANS(NAME, AVAIL, FUNC, ...) \
2862 static bool trans_##NAME(DisasContext *dc, arg_##NAME *a) \
2863 { return avail_##AVAIL(dc) && FUNC(dc, __VA_ARGS__); }
2864
2865#define avail_ALL(C) true
2866#ifdef TARGET_SPARC64
2867# define avail_32(C) false
2868# define avail_ASR17(C) false
51# define MAXTL_MASK 0
52#endif
53
54/* Dynamic PC, must exit to main loop. */
55#define DYNAMIC_PC 1
56/* Dynamic PC, one of two values according to jump_pc[T2]. */
57#define JUMP_PC 2
58/* Dynamic PC, may lookup next TB. */

--- 2807 unchanged lines hidden (view full) ---

2866#define TRANS(NAME, AVAIL, FUNC, ...) \
2867 static bool trans_##NAME(DisasContext *dc, arg_##NAME *a) \
2868 { return avail_##AVAIL(dc) && FUNC(dc, __VA_ARGS__); }
2869
2870#define avail_ALL(C) true
2871#ifdef TARGET_SPARC64
2872# define avail_32(C) false
2873# define avail_ASR17(C) false
2874# define avail_POWERDOWN(C) false
2869# define avail_64(C) true
2870# define avail_GL(C) ((C)->def->features & CPU_FEATURE_GL)
2871# define avail_HYPV(C) ((C)->def->features & CPU_FEATURE_HYPV)
2872#else
2873# define avail_32(C) true
2874# define avail_ASR17(C) ((C)->def->features & CPU_FEATURE_ASR17)
2875# define avail_64(C) true
2876# define avail_GL(C) ((C)->def->features & CPU_FEATURE_GL)
2877# define avail_HYPV(C) ((C)->def->features & CPU_FEATURE_HYPV)
2878#else
2879# define avail_32(C) true
2880# define avail_ASR17(C) ((C)->def->features & CPU_FEATURE_ASR17)
2881# define avail_POWERDOWN(C) ((C)->def->features & CPU_FEATURE_POWERDOWN)
2875# define avail_64(C) false
2876# define avail_GL(C) false
2877# define avail_HYPV(C) false
2878#endif
2879
2880/* Default case for non jump instructions. */
2881static bool advance_pc(DisasContext *dc)
2882{

--- 189 unchanged lines hidden (view full) ---

3072{
3073 /* Special-case %g0 because that's the canonical nop. */
3074 if (a->rd) {
3075 gen_store_gpr(dc, a->rd, tcg_constant_tl((uint32_t)a->i << 10));
3076 }
3077 return advance_pc(dc);
3078}
3079
2882# define avail_64(C) false
2883# define avail_GL(C) false
2884# define avail_HYPV(C) false
2885#endif
2886
2887/* Default case for non jump instructions. */
2888static bool advance_pc(DisasContext *dc)
2889{

--- 189 unchanged lines hidden (view full) ---

3079{
3080 /* Special-case %g0 because that's the canonical nop. */
3081 if (a->rd) {
3082 gen_store_gpr(dc, a->rd, tcg_constant_tl((uint32_t)a->i << 10));
3083 }
3084 return advance_pc(dc);
3085}
3086
3087/*
3088 * Major Opcode 10 -- integer, floating-point, vis, and system insns.
3089 */
3090
3080static bool do_tcc(DisasContext *dc, int cond, int cc,
3081 int rs1, bool imm, int rs2_or_imm)
3082{
3083 int mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc)
3084 ? UA2005_HTRAP_MASK : V8_TRAP_MASK);
3085 DisasCompare cmp;
3086 TCGLabel *lab;
3087 TCGv_i32 trap;

--- 480 unchanged lines hidden (view full) ---

3568{
3569 if (avail_64(dc)) {
3570 gen_helper_flushw(tcg_env);
3571 return advance_pc(dc);
3572 }
3573 return false;
3574}
3575
3091static bool do_tcc(DisasContext *dc, int cond, int cc,
3092 int rs1, bool imm, int rs2_or_imm)
3093{
3094 int mask = ((dc->def->features & CPU_FEATURE_HYPV) && supervisor(dc)
3095 ? UA2005_HTRAP_MASK : V8_TRAP_MASK);
3096 DisasCompare cmp;
3097 TCGLabel *lab;
3098 TCGv_i32 trap;

--- 480 unchanged lines hidden (view full) ---

3579{
3580 if (avail_64(dc)) {
3581 gen_helper_flushw(tcg_env);
3582 return advance_pc(dc);
3583 }
3584 return false;
3585}
3586
3587static bool do_wr_special(DisasContext *dc, arg_r_r_ri *a, bool priv,
3588 void (*func)(DisasContext *, TCGv))
3589{
3590 TCGv src;
3591
3592 /* For simplicity, we under-decoded the rs2 form. */
3593 if (!a->imm && (a->rs2_or_imm & ~0x1f)) {
3594 return false;
3595 }
3596 if (!priv) {
3597 return raise_priv(dc);
3598 }
3599
3600 if (a->rs1 == 0 && (a->imm || a->rs2_or_imm == 0)) {
3601 src = tcg_constant_tl(a->rs2_or_imm);
3602 } else {
3603 TCGv src1 = gen_load_gpr(dc, a->rs1);
3604 if (a->rs2_or_imm == 0) {
3605 src = src1;
3606 } else {
3607 src = tcg_temp_new();
3608 if (a->imm) {
3609 tcg_gen_xori_tl(src, src1, a->rs2_or_imm);
3610 } else {
3611 tcg_gen_xor_tl(src, src1, gen_load_gpr(dc, a->rs2_or_imm));
3612 }
3613 }
3614 }
3615 func(dc, src);
3616 return advance_pc(dc);
3617}
3618
3619static void do_wry(DisasContext *dc, TCGv src)
3620{
3621 tcg_gen_ext32u_tl(cpu_y, src);
3622}
3623
3624TRANS(WRY, ALL, do_wr_special, a, true, do_wry)
3625
3626static void do_wrccr(DisasContext *dc, TCGv src)
3627{
3628 gen_helper_wrccr(tcg_env, src);
3629}
3630
3631TRANS(WRCCR, 64, do_wr_special, a, true, do_wrccr)
3632
3633static void do_wrasi(DisasContext *dc, TCGv src)
3634{
3635 TCGv tmp = tcg_temp_new();
3636
3637 tcg_gen_ext8u_tl(tmp, src);
3638 tcg_gen_st32_tl(tmp, tcg_env, env64_field_offsetof(asi));
3639 /* End TB to notice changed ASI. */
3640 dc->base.is_jmp = DISAS_EXIT;
3641}
3642
3643TRANS(WRASI, 64, do_wr_special, a, true, do_wrasi)
3644
3645static void do_wrfprs(DisasContext *dc, TCGv src)
3646{
3647#ifdef TARGET_SPARC64
3648 tcg_gen_trunc_tl_i32(cpu_fprs, src);
3649 dc->fprs_dirty = 0;
3650 dc->base.is_jmp = DISAS_EXIT;
3651#else
3652 qemu_build_not_reached();
3653#endif
3654}
3655
3656TRANS(WRFPRS, 64, do_wr_special, a, true, do_wrfprs)
3657
3658static void do_wrgsr(DisasContext *dc, TCGv src)
3659{
3660 gen_trap_ifnofpu(dc);
3661 tcg_gen_mov_tl(cpu_gsr, src);
3662}
3663
3664TRANS(WRGSR, 64, do_wr_special, a, true, do_wrgsr)
3665
3666static void do_wrsoftint_set(DisasContext *dc, TCGv src)
3667{
3668 gen_helper_set_softint(tcg_env, src);
3669}
3670
3671TRANS(WRSOFTINT_SET, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_set)
3672
3673static void do_wrsoftint_clr(DisasContext *dc, TCGv src)
3674{
3675 gen_helper_clear_softint(tcg_env, src);
3676}
3677
3678TRANS(WRSOFTINT_CLR, 64, do_wr_special, a, supervisor(dc), do_wrsoftint_clr)
3679
3680static void do_wrsoftint(DisasContext *dc, TCGv src)
3681{
3682 gen_helper_write_softint(tcg_env, src);
3683}
3684
3685TRANS(WRSOFTINT, 64, do_wr_special, a, supervisor(dc), do_wrsoftint)
3686
3687static void do_wrtick_cmpr(DisasContext *dc, TCGv src)
3688{
3689#ifdef TARGET_SPARC64
3690 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3691
3692 tcg_gen_mov_tl(cpu_tick_cmpr, src);
3693 tcg_gen_ld_ptr(r_tickptr, tcg_env, offsetof(CPUSPARCState, tick));
3694 translator_io_start(&dc->base);
3695 gen_helper_tick_set_limit(r_tickptr, cpu_tick_cmpr);
3696 /* End TB to handle timer interrupt */
3697 dc->base.is_jmp = DISAS_EXIT;
3698#else
3699 qemu_build_not_reached();
3700#endif
3701}
3702
3703TRANS(WRTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrtick_cmpr)
3704
3705static void do_wrstick(DisasContext *dc, TCGv src)
3706{
3707#ifdef TARGET_SPARC64
3708 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3709
3710 tcg_gen_ld_ptr(r_tickptr, tcg_env, offsetof(CPUSPARCState, stick));
3711 translator_io_start(&dc->base);
3712 gen_helper_tick_set_count(r_tickptr, src);
3713 /* End TB to handle timer interrupt */
3714 dc->base.is_jmp = DISAS_EXIT;
3715#else
3716 qemu_build_not_reached();
3717#endif
3718}
3719
3720TRANS(WRSTICK, 64, do_wr_special, a, supervisor(dc), do_wrstick)
3721
3722static void do_wrstick_cmpr(DisasContext *dc, TCGv src)
3723{
3724#ifdef TARGET_SPARC64
3725 TCGv_ptr r_tickptr = tcg_temp_new_ptr();
3726
3727 tcg_gen_mov_tl(cpu_stick_cmpr, src);
3728 tcg_gen_ld_ptr(r_tickptr, tcg_env, offsetof(CPUSPARCState, stick));
3729 translator_io_start(&dc->base);
3730 gen_helper_tick_set_limit(r_tickptr, cpu_stick_cmpr);
3731 /* End TB to handle timer interrupt */
3732 dc->base.is_jmp = DISAS_EXIT;
3733#else
3734 qemu_build_not_reached();
3735#endif
3736}
3737
3738TRANS(WRSTICK_CMPR, 64, do_wr_special, a, supervisor(dc), do_wrstick_cmpr)
3739
3740static void do_wrpowerdown(DisasContext *dc, TCGv src)
3741{
3742 save_state(dc);
3743 gen_helper_power_down(tcg_env);
3744}
3745
3746TRANS(WRPOWERDOWN, POWERDOWN, do_wr_special, a, supervisor(dc), do_wrpowerdown)
3747
3748static bool trans_NOP_v7(DisasContext *dc, arg_NOP_v7 *a)
3749{
3750 /*
3751 * TODO: Need a feature bit for sparcv8.
3752 * In the meantime, treat all 32-bit cpus like sparcv7.
3753 */
3754 if (avail_32(dc)) {
3755 return advance_pc(dc);
3756 }
3757 return false;
3758}
3759
3576#define CHECK_IU_FEATURE(dc, FEATURE) \
3577 if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
3578 goto illegal_insn;
3579#define CHECK_FPU_FEATURE(dc, FEATURE) \
3580 if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
3581 goto nfpu_insn;
3582
3583/* before an instruction, dc->pc must be static */

--- 644 unchanged lines hidden (view full) ---

4228 cpu_tmp0 = tcg_temp_new();
4229 tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
4230 tcg_gen_sar_tl(cpu_dst, cpu_src1, cpu_tmp0);
4231 }
4232 gen_store_gpr(dc, rd, cpu_dst);
4233 break;
4234#endif
4235 case 0x30:
3760#define CHECK_IU_FEATURE(dc, FEATURE) \
3761 if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
3762 goto illegal_insn;
3763#define CHECK_FPU_FEATURE(dc, FEATURE) \
3764 if (!((dc)->def->features & CPU_FEATURE_ ## FEATURE)) \
3765 goto nfpu_insn;
3766
3767/* before an instruction, dc->pc must be static */

--- 644 unchanged lines hidden (view full) ---

4412 cpu_tmp0 = tcg_temp_new();
4413 tcg_gen_andi_tl(cpu_tmp0, cpu_src2, 0x1f);
4414 tcg_gen_sar_tl(cpu_dst, cpu_src1, cpu_tmp0);
4415 }
4416 gen_store_gpr(dc, rd, cpu_dst);
4417 break;
4418#endif
4419 case 0x30:
4236 {
4237 cpu_tmp0 = tcg_temp_new();
4238 switch(rd) {
4239 case 0: /* wry */
4240 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
4241 tcg_gen_andi_tl(cpu_y, cpu_tmp0, 0xffffffff);
4242 break;
4243#ifndef TARGET_SPARC64
4244 case 0x01 ... 0x0f: /* undefined in the
4245 SPARCv8 manual, nop
4246 on the microSPARC
4247 II */
4248 case 0x10 ... 0x1f: /* implementation-dependent
4249 in the SPARCv8
4250 manual, nop on the
4251 microSPARC II */
4252 if ((rd == 0x13) && (dc->def->features &
4253 CPU_FEATURE_POWERDOWN)) {
4254 /* LEON3 power-down */
4255 save_state(dc);
4256 gen_helper_power_down(tcg_env);
4257 }
4258 break;
4259#else
4260 case 0x2: /* V9 wrccr */
4261 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
4262 gen_helper_wrccr(tcg_env, cpu_tmp0);
4263 tcg_gen_movi_i32(cpu_cc_op, CC_OP_FLAGS);
4264 dc->cc_op = CC_OP_FLAGS;
4265 break;
4266 case 0x3: /* V9 wrasi */
4267 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
4268 tcg_gen_andi_tl(cpu_tmp0, cpu_tmp0, 0xff);
4269 tcg_gen_st32_tl(cpu_tmp0, tcg_env,
4270 offsetof(CPUSPARCState, asi));
4271 /*
4272 * End TB to notice changed ASI.
4273 * TODO: Could notice src1 = %g0 and IS_IMM,
4274 * update DisasContext and not exit the TB.
4275 */
4276 save_state(dc);
4277 gen_op_next_insn();
4278 tcg_gen_lookup_and_goto_ptr();
4279 dc->base.is_jmp = DISAS_NORETURN;
4280 break;
4281 case 0x6: /* V9 wrfprs */
4282 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
4283 tcg_gen_trunc_tl_i32(cpu_fprs, cpu_tmp0);
4284 dc->fprs_dirty = 0;
4285 save_state(dc);
4286 gen_op_next_insn();
4287 tcg_gen_exit_tb(NULL, 0);
4288 dc->base.is_jmp = DISAS_NORETURN;
4289 break;
4290 case 0xf: /* V9 sir, nop if user */
4420 goto illegal_insn; /* WRASR in decodetree */
4291#if !defined(CONFIG_USER_ONLY)
4421#if !defined(CONFIG_USER_ONLY)
4292 if (supervisor(dc)) {
4293 ; // XXX
4294 }
4295#endif
4296 break;
4297 case 0x13: /* Graphics Status */
4298 if (gen_trap_ifnofpu(dc)) {
4299 goto jmp_insn;
4300 }
4301 tcg_gen_xor_tl(cpu_gsr, cpu_src1, cpu_src2);
4302 break;
4303 case 0x14: /* Softint set */
4304 if (!supervisor(dc))
4305 goto illegal_insn;
4306 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
4307 gen_helper_set_softint(tcg_env, cpu_tmp0);
4308 break;
4309 case 0x15: /* Softint clear */
4310 if (!supervisor(dc))
4311 goto illegal_insn;
4312 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
4313 gen_helper_clear_softint(tcg_env, cpu_tmp0);
4314 break;
4315 case 0x16: /* Softint write */
4316 if (!supervisor(dc))
4317 goto illegal_insn;
4318 tcg_gen_xor_tl(cpu_tmp0, cpu_src1, cpu_src2);
4319 gen_helper_write_softint(tcg_env, cpu_tmp0);
4320 break;
4321 case 0x17: /* Tick compare */
4322#if !defined(CONFIG_USER_ONLY)
4323 if (!supervisor(dc))
4324 goto illegal_insn;
4325#endif
4326 {
4327 TCGv_ptr r_tickptr;
4328
4329 tcg_gen_xor_tl(cpu_tick_cmpr, cpu_src1,
4330 cpu_src2);
4331 r_tickptr = tcg_temp_new_ptr();
4332 tcg_gen_ld_ptr(r_tickptr, tcg_env,
4333 offsetof(CPUSPARCState, tick));
4334 translator_io_start(&dc->base);
4335 gen_helper_tick_set_limit(r_tickptr,
4336 cpu_tick_cmpr);
4337 /* End TB to handle timer interrupt */
4338 dc->base.is_jmp = DISAS_EXIT;
4339 }
4340 break;
4341 case 0x18: /* System tick */
4342#if !defined(CONFIG_USER_ONLY)
4343 if (!supervisor(dc))
4344 goto illegal_insn;
4345#endif
4346 {
4347 TCGv_ptr r_tickptr;
4348
4349 tcg_gen_xor_tl(cpu_tmp0, cpu_src1,
4350 cpu_src2);
4351 r_tickptr = tcg_temp_new_ptr();
4352 tcg_gen_ld_ptr(r_tickptr, tcg_env,
4353 offsetof(CPUSPARCState, stick));
4354 translator_io_start(&dc->base);
4355 gen_helper_tick_set_count(r_tickptr,
4356 cpu_tmp0);
4357 /* End TB to handle timer interrupt */
4358 dc->base.is_jmp = DISAS_EXIT;
4359 }
4360 break;
4361 case 0x19: /* System tick compare */
4362#if !defined(CONFIG_USER_ONLY)
4363 if (!supervisor(dc))
4364 goto illegal_insn;
4365#endif
4366 {
4367 TCGv_ptr r_tickptr;
4368
4369 tcg_gen_xor_tl(cpu_stick_cmpr, cpu_src1,
4370 cpu_src2);
4371 r_tickptr = tcg_temp_new_ptr();
4372 tcg_gen_ld_ptr(r_tickptr, tcg_env,
4373 offsetof(CPUSPARCState, stick));
4374 translator_io_start(&dc->base);
4375 gen_helper_tick_set_limit(r_tickptr,
4376 cpu_stick_cmpr);
4377 /* End TB to handle timer interrupt */
4378 dc->base.is_jmp = DISAS_EXIT;
4379 }
4380 break;
4381
4382 case 0x10: /* Performance Control */
4383 case 0x11: /* Performance Instrumentation
4384 Counter */
4385 case 0x12: /* Dispatch Control */
4386#endif
4387 default:
4388 goto illegal_insn;
4389 }
4390 }
4391 break;
4392#if !defined(CONFIG_USER_ONLY)
4393 case 0x31: /* wrpsr, V9 saved, restored */
4394 {
4395 if (!supervisor(dc))
4396 goto priv_insn;
4397#ifdef TARGET_SPARC64
4398 switch (rd) {
4399 case 0:
4400 gen_helper_saved(tcg_env);

--- 1558 unchanged lines hidden ---
4422 case 0x31: /* wrpsr, V9 saved, restored */
4423 {
4424 if (!supervisor(dc))
4425 goto priv_insn;
4426#ifdef TARGET_SPARC64
4427 switch (rd) {
4428 case 0:
4429 gen_helper_saved(tcg_env);

--- 1558 unchanged lines hidden ---