translate.c (0c2e96c1703041badf675993247351f629b4ab20) | translate.c (633c42834c7bbd528fdb0971c3d2f994a5137072) |
---|---|
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 --- 23 unchanged lines hidden (view full) --- 32#include "exec/translator.h" 33#include "exec/log.h" 34#include "asi.h" 35 36#define HELPER_H "helper.h" 37#include "exec/helper-info.c.inc" 38#undef HELPER_H 39 | 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 --- 23 unchanged lines hidden (view full) --- 32#include "exec/translator.h" 33#include "exec/log.h" 34#include "asi.h" 35 36#define HELPER_H "helper.h" 37#include "exec/helper-info.c.inc" 38#undef HELPER_H 39 |
40#define DYNAMIC_PC 1 /* dynamic pc value */ 41#define JUMP_PC 2 /* dynamic pc value which takes only two values 42 according to jump_pc[T2] */ | 40/* Dynamic PC, must exit to main loop. */ 41#define DYNAMIC_PC 1 42/* Dynamic PC, one of two values according to jump_pc[T2]. */ 43#define JUMP_PC 2 44/* Dynamic PC, may lookup next TB. */ 45#define DYNAMIC_PC_LOOKUP 3 |
43 44#define DISAS_EXIT DISAS_TARGET_0 45 46/* global register indexes */ 47static TCGv_ptr cpu_regwptr; 48static TCGv cpu_cc_src, cpu_cc_src2, cpu_cc_dst; 49static TCGv_i32 cpu_cc_op; 50static TCGv_i32 cpu_psr; --- 845 unchanged lines hidden (view full) --- 896 897 dc->base.is_jmp = DISAS_NORETURN; 898} 899 900static void gen_branch_n(DisasContext *dc, target_ulong pc1) 901{ 902 target_ulong npc = dc->npc; 903 | 46 47#define DISAS_EXIT DISAS_TARGET_0 48 49/* global register indexes */ 50static TCGv_ptr cpu_regwptr; 51static TCGv cpu_cc_src, cpu_cc_src2, cpu_cc_dst; 52static TCGv_i32 cpu_cc_op; 53static TCGv_i32 cpu_psr; --- 845 unchanged lines hidden (view full) --- 899 900 dc->base.is_jmp = DISAS_NORETURN; 901} 902 903static void gen_branch_n(DisasContext *dc, target_ulong pc1) 904{ 905 target_ulong npc = dc->npc; 906 |
904 if (likely(npc != DYNAMIC_PC)) { | 907 if (npc & 3) { 908 switch (npc) { 909 case DYNAMIC_PC: 910 case DYNAMIC_PC_LOOKUP: 911 tcg_gen_mov_tl(cpu_pc, cpu_npc); 912 tcg_gen_addi_tl(cpu_npc, cpu_npc, 4); 913 tcg_gen_movcond_tl(TCG_COND_NE, cpu_npc, 914 cpu_cond, tcg_constant_tl(0), 915 tcg_constant_tl(pc1), cpu_npc); 916 dc->pc = npc; 917 break; 918 default: 919 g_assert_not_reached(); 920 } 921 } else { |
905 dc->pc = npc; 906 dc->jump_pc[0] = pc1; 907 dc->jump_pc[1] = npc + 4; 908 dc->npc = JUMP_PC; | 922 dc->pc = npc; 923 dc->jump_pc[0] = pc1; 924 dc->jump_pc[1] = npc + 4; 925 dc->npc = JUMP_PC; |
909 } else { 910 TCGv t, z; 911 912 tcg_gen_mov_tl(cpu_pc, cpu_npc); 913 914 tcg_gen_addi_tl(cpu_npc, cpu_npc, 4); 915 t = tcg_constant_tl(pc1); 916 z = tcg_constant_tl(0); 917 tcg_gen_movcond_tl(TCG_COND_NE, cpu_npc, cpu_cond, z, t, cpu_npc); 918 919 dc->pc = DYNAMIC_PC; | |
920 } 921} 922 923static void gen_generic_branch(DisasContext *dc) 924{ 925 TCGv npc0 = tcg_constant_tl(dc->jump_pc[0]); 926 TCGv npc1 = tcg_constant_tl(dc->jump_pc[1]); 927 TCGv zero = tcg_constant_tl(0); --- 8 unchanged lines hidden (view full) --- 936 if (dc->npc == JUMP_PC) { 937 gen_generic_branch(dc); 938 dc->npc = DYNAMIC_PC; 939 } 940} 941 942static void save_npc(DisasContext *dc) 943{ | 926 } 927} 928 929static void gen_generic_branch(DisasContext *dc) 930{ 931 TCGv npc0 = tcg_constant_tl(dc->jump_pc[0]); 932 TCGv npc1 = tcg_constant_tl(dc->jump_pc[1]); 933 TCGv zero = tcg_constant_tl(0); --- 8 unchanged lines hidden (view full) --- 942 if (dc->npc == JUMP_PC) { 943 gen_generic_branch(dc); 944 dc->npc = DYNAMIC_PC; 945 } 946} 947 948static void save_npc(DisasContext *dc) 949{ |
944 if (dc->npc == JUMP_PC) { 945 gen_generic_branch(dc); 946 dc->npc = DYNAMIC_PC; 947 } else if (dc->npc != DYNAMIC_PC) { | 950 if (dc->npc & 3) { 951 switch (dc->npc) { 952 case JUMP_PC: 953 gen_generic_branch(dc); 954 dc->npc = DYNAMIC_PC; 955 break; 956 case DYNAMIC_PC: 957 case DYNAMIC_PC_LOOKUP: 958 break; 959 default: 960 g_assert_not_reached(); 961 } 962 } else { |
948 tcg_gen_movi_tl(cpu_npc, dc->npc); 949 } 950} 951 952static void update_psr(DisasContext *dc) 953{ 954 if (dc->cc_op != CC_OP_FLAGS) { 955 dc->cc_op = CC_OP_FLAGS; --- 16 unchanged lines hidden (view full) --- 972 973static void gen_check_align(TCGv addr, int mask) 974{ 975 gen_helper_check_align(cpu_env, addr, tcg_constant_i32(mask)); 976} 977 978static void gen_mov_pc_npc(DisasContext *dc) 979{ | 963 tcg_gen_movi_tl(cpu_npc, dc->npc); 964 } 965} 966 967static void update_psr(DisasContext *dc) 968{ 969 if (dc->cc_op != CC_OP_FLAGS) { 970 dc->cc_op = CC_OP_FLAGS; --- 16 unchanged lines hidden (view full) --- 987 988static void gen_check_align(TCGv addr, int mask) 989{ 990 gen_helper_check_align(cpu_env, addr, tcg_constant_i32(mask)); 991} 992 993static void gen_mov_pc_npc(DisasContext *dc) 994{ |
980 if (dc->npc == JUMP_PC) { 981 gen_generic_branch(dc); 982 tcg_gen_mov_tl(cpu_pc, cpu_npc); 983 dc->pc = DYNAMIC_PC; 984 } else if (dc->npc == DYNAMIC_PC) { 985 tcg_gen_mov_tl(cpu_pc, cpu_npc); 986 dc->pc = DYNAMIC_PC; | 995 if (dc->npc & 3) { 996 switch (dc->npc) { 997 case JUMP_PC: 998 gen_generic_branch(dc); 999 tcg_gen_mov_tl(cpu_pc, cpu_npc); 1000 dc->pc = DYNAMIC_PC; 1001 break; 1002 case DYNAMIC_PC: 1003 case DYNAMIC_PC_LOOKUP: 1004 tcg_gen_mov_tl(cpu_pc, cpu_npc); 1005 dc->pc = dc->npc; 1006 break; 1007 default: 1008 g_assert_not_reached(); 1009 } |
987 } else { 988 dc->pc = dc->npc; 989 } 990} 991 992static void gen_op_next_insn(void) 993{ 994 tcg_gen_mov_tl(cpu_pc, cpu_npc); --- 4501 unchanged lines hidden (view full) --- 5496 } 5497 } else { 5498 goto illegal_insn; 5499 } 5500 } 5501 break; 5502 } 5503 /* default case for non jump instructions */ | 1010 } else { 1011 dc->pc = dc->npc; 1012 } 1013} 1014 1015static void gen_op_next_insn(void) 1016{ 1017 tcg_gen_mov_tl(cpu_pc, cpu_npc); --- 4501 unchanged lines hidden (view full) --- 5519 } 5520 } else { 5521 goto illegal_insn; 5522 } 5523 } 5524 break; 5525 } 5526 /* default case for non jump instructions */ |
5504 if (dc->npc == DYNAMIC_PC) { 5505 dc->pc = DYNAMIC_PC; 5506 gen_op_next_insn(); 5507 } else if (dc->npc == JUMP_PC) { 5508 /* we can do a static jump */ 5509 gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1], cpu_cond); 5510 dc->base.is_jmp = DISAS_NORETURN; | 5527 if (dc->npc & 3) { 5528 switch (dc->npc) { 5529 case DYNAMIC_PC: 5530 case DYNAMIC_PC_LOOKUP: 5531 dc->pc = dc->npc; 5532 gen_op_next_insn(); 5533 break; 5534 case JUMP_PC: 5535 /* we can do a static jump */ 5536 gen_branch2(dc, dc->jump_pc[0], dc->jump_pc[1], cpu_cond); 5537 dc->base.is_jmp = DISAS_NORETURN; 5538 break; 5539 default: 5540 g_assert_not_reached(); 5541 } |
5511 } else { 5512 dc->pc = dc->npc; 5513 dc->npc = dc->npc + 4; 5514 } 5515 jmp_insn: 5516 return; 5517 illegal_insn: 5518 gen_exception(dc, TT_ILL_INSN); --- 54 unchanged lines hidden (view full) --- 5573 5574static void sparc_tr_tb_start(DisasContextBase *db, CPUState *cs) 5575{ 5576} 5577 5578static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) 5579{ 5580 DisasContext *dc = container_of(dcbase, DisasContext, base); | 5542 } else { 5543 dc->pc = dc->npc; 5544 dc->npc = dc->npc + 4; 5545 } 5546 jmp_insn: 5547 return; 5548 illegal_insn: 5549 gen_exception(dc, TT_ILL_INSN); --- 54 unchanged lines hidden (view full) --- 5604 5605static void sparc_tr_tb_start(DisasContextBase *db, CPUState *cs) 5606{ 5607} 5608 5609static void sparc_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) 5610{ 5611 DisasContext *dc = container_of(dcbase, DisasContext, base); |
5612 target_ulong npc = dc->npc; |
|
5581 | 5613 |
5582 if (dc->npc == JUMP_PC) { 5583 assert(dc->jump_pc[1] == dc->pc + 4); 5584 tcg_gen_insn_start(dc->pc, dc->jump_pc[0] | JUMP_PC); 5585 } else { 5586 tcg_gen_insn_start(dc->pc, dc->npc); | 5614 if (npc & 3) { 5615 switch (npc) { 5616 case JUMP_PC: 5617 assert(dc->jump_pc[1] == dc->pc + 4); 5618 npc = dc->jump_pc[0] | JUMP_PC; 5619 break; 5620 case DYNAMIC_PC: 5621 case DYNAMIC_PC_LOOKUP: 5622 npc = DYNAMIC_PC; 5623 break; 5624 default: 5625 g_assert_not_reached(); 5626 } |
5587 } | 5627 } |
5628 tcg_gen_insn_start(dc->pc, npc); |
|
5588} 5589 5590static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 5591{ 5592 DisasContext *dc = container_of(dcbase, DisasContext, base); 5593 CPUSPARCState *env = cs->env_ptr; 5594 unsigned int insn; 5595 --- 7 unchanged lines hidden (view full) --- 5603 if (dc->pc != dc->base.pc_next) { 5604 dc->base.is_jmp = DISAS_TOO_MANY; 5605 } 5606} 5607 5608static void sparc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 5609{ 5610 DisasContext *dc = container_of(dcbase, DisasContext, base); | 5629} 5630 5631static void sparc_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) 5632{ 5633 DisasContext *dc = container_of(dcbase, DisasContext, base); 5634 CPUSPARCState *env = cs->env_ptr; 5635 unsigned int insn; 5636 --- 7 unchanged lines hidden (view full) --- 5644 if (dc->pc != dc->base.pc_next) { 5645 dc->base.is_jmp = DISAS_TOO_MANY; 5646 } 5647} 5648 5649static void sparc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) 5650{ 5651 DisasContext *dc = container_of(dcbase, DisasContext, base); |
5652 bool may_lookup; |
|
5611 5612 switch (dc->base.is_jmp) { 5613 case DISAS_NEXT: 5614 case DISAS_TOO_MANY: | 5653 5654 switch (dc->base.is_jmp) { 5655 case DISAS_NEXT: 5656 case DISAS_TOO_MANY: |
5615 if (dc->pc != DYNAMIC_PC && 5616 (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) { | 5657 if (((dc->pc | dc->npc) & 3) == 0) { |
5617 /* static PC and NPC: we can use direct chaining */ 5618 gen_goto_tb(dc, 0, dc->pc, dc->npc); | 5658 /* static PC and NPC: we can use direct chaining */ 5659 gen_goto_tb(dc, 0, dc->pc, dc->npc); |
5619 } else { 5620 if (dc->pc != DYNAMIC_PC) { 5621 tcg_gen_movi_tl(cpu_pc, dc->pc); | 5660 break; 5661 } 5662 5663 if (dc->pc & 3) { 5664 switch (dc->pc) { 5665 case DYNAMIC_PC_LOOKUP: 5666 may_lookup = true; 5667 break; 5668 case DYNAMIC_PC: 5669 may_lookup = false; 5670 break; 5671 default: 5672 g_assert_not_reached(); |
5622 } | 5673 } |
5623 save_npc(dc); | 5674 } else { 5675 tcg_gen_movi_tl(cpu_pc, dc->pc); 5676 may_lookup = true; 5677 } 5678 5679 save_npc(dc); 5680 if (may_lookup) { 5681 tcg_gen_lookup_and_goto_ptr(); 5682 } else { |
5624 tcg_gen_exit_tb(NULL, 0); 5625 } 5626 break; 5627 5628 case DISAS_NORETURN: 5629 break; 5630 5631 case DISAS_EXIT: --- 143 unchanged lines hidden --- | 5683 tcg_gen_exit_tb(NULL, 0); 5684 } 5685 break; 5686 5687 case DISAS_NORETURN: 5688 break; 5689 5690 case DISAS_EXIT: --- 143 unchanged lines hidden --- |