📄 translate.c
字号:
/* SPARC translation Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at> Copyright (C) 2003-2005 Fabrice Bellard This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* TODO-list: Rest of V9 instructions, VIS instructions NPC/PC static optimisations (use JUMP_TB when possible) Optimize synthetic instructions Optional alignment check 128-bit float Tagged add/sub*/#include <stdarg.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <inttypes.h>#include "cpu.h"#include "exec-all.h"#include "disas.h"#define DEBUG_DISAS#define DYNAMIC_PC 1 /* dynamic pc value */#define JUMP_PC 2 /* dynamic pc value which takes only two values according to jump_pc[T2] */typedef struct DisasContext { target_ulong pc; /* current Program Counter: integer or DYNAMIC_PC */ target_ulong npc; /* next PC: integer or DYNAMIC_PC or JUMP_PC */ target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */ int is_br; int mem_idx; struct TranslationBlock *tb;} DisasContext;static uint16_t *gen_opc_ptr;static uint32_t *gen_opparam_ptr;extern FILE *logfile;extern int loglevel;enum {#define DEF(s,n,copy_size) INDEX_op_ ## s,#include "opc.h"#undef DEF NB_OPS};#include "gen-op.h"// This function uses non-native bit order#define GET_FIELD(X, FROM, TO) \ ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))// This function uses the order in the manuals, i.e. bit 0 is 2^0#define GET_FIELD_SP(X, FROM, TO) \ GET_FIELD(X, 31 - (TO), 31 - (FROM))#define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)#define GET_FIELD_SPs(x,a,b) sign_extend (GET_FIELD_SP(x,a,b), 32 - ((b) - (a) + 1))#ifdef TARGET_SPARC64#define DFPREG(r) (((r & 1) << 6) | (r & 0x1e))#else#define DFPREG(r) (r)#endif#ifdef USE_DIRECT_JUMP#define TBPARAM(x)#else#define TBPARAM(x) (long)(x)#endifstatic int sign_extend(int x, int len){ len = 32 - len; return (x << len) >> len;}#define IS_IMM (insn & (1<<13))static void disas_sparc_insn(DisasContext * dc);static GenOpFunc *gen_op_movl_TN_reg[2][32] = { { gen_op_movl_g0_T0, gen_op_movl_g1_T0, gen_op_movl_g2_T0, gen_op_movl_g3_T0, gen_op_movl_g4_T0, gen_op_movl_g5_T0, gen_op_movl_g6_T0, gen_op_movl_g7_T0, gen_op_movl_o0_T0, gen_op_movl_o1_T0, gen_op_movl_o2_T0, gen_op_movl_o3_T0, gen_op_movl_o4_T0, gen_op_movl_o5_T0, gen_op_movl_o6_T0, gen_op_movl_o7_T0, gen_op_movl_l0_T0, gen_op_movl_l1_T0, gen_op_movl_l2_T0, gen_op_movl_l3_T0, gen_op_movl_l4_T0, gen_op_movl_l5_T0, gen_op_movl_l6_T0, gen_op_movl_l7_T0, gen_op_movl_i0_T0, gen_op_movl_i1_T0, gen_op_movl_i2_T0, gen_op_movl_i3_T0, gen_op_movl_i4_T0, gen_op_movl_i5_T0, gen_op_movl_i6_T0, gen_op_movl_i7_T0, }, { gen_op_movl_g0_T1, gen_op_movl_g1_T1, gen_op_movl_g2_T1, gen_op_movl_g3_T1, gen_op_movl_g4_T1, gen_op_movl_g5_T1, gen_op_movl_g6_T1, gen_op_movl_g7_T1, gen_op_movl_o0_T1, gen_op_movl_o1_T1, gen_op_movl_o2_T1, gen_op_movl_o3_T1, gen_op_movl_o4_T1, gen_op_movl_o5_T1, gen_op_movl_o6_T1, gen_op_movl_o7_T1, gen_op_movl_l0_T1, gen_op_movl_l1_T1, gen_op_movl_l2_T1, gen_op_movl_l3_T1, gen_op_movl_l4_T1, gen_op_movl_l5_T1, gen_op_movl_l6_T1, gen_op_movl_l7_T1, gen_op_movl_i0_T1, gen_op_movl_i1_T1, gen_op_movl_i2_T1, gen_op_movl_i3_T1, gen_op_movl_i4_T1, gen_op_movl_i5_T1, gen_op_movl_i6_T1, gen_op_movl_i7_T1, }};static GenOpFunc *gen_op_movl_reg_TN[3][32] = { { gen_op_movl_T0_g0, gen_op_movl_T0_g1, gen_op_movl_T0_g2, gen_op_movl_T0_g3, gen_op_movl_T0_g4, gen_op_movl_T0_g5, gen_op_movl_T0_g6, gen_op_movl_T0_g7, gen_op_movl_T0_o0, gen_op_movl_T0_o1, gen_op_movl_T0_o2, gen_op_movl_T0_o3, gen_op_movl_T0_o4, gen_op_movl_T0_o5, gen_op_movl_T0_o6, gen_op_movl_T0_o7, gen_op_movl_T0_l0, gen_op_movl_T0_l1, gen_op_movl_T0_l2, gen_op_movl_T0_l3, gen_op_movl_T0_l4, gen_op_movl_T0_l5, gen_op_movl_T0_l6, gen_op_movl_T0_l7, gen_op_movl_T0_i0, gen_op_movl_T0_i1, gen_op_movl_T0_i2, gen_op_movl_T0_i3, gen_op_movl_T0_i4, gen_op_movl_T0_i5, gen_op_movl_T0_i6, gen_op_movl_T0_i7, }, { gen_op_movl_T1_g0, gen_op_movl_T1_g1, gen_op_movl_T1_g2, gen_op_movl_T1_g3, gen_op_movl_T1_g4, gen_op_movl_T1_g5, gen_op_movl_T1_g6, gen_op_movl_T1_g7, gen_op_movl_T1_o0, gen_op_movl_T1_o1, gen_op_movl_T1_o2, gen_op_movl_T1_o3, gen_op_movl_T1_o4, gen_op_movl_T1_o5, gen_op_movl_T1_o6, gen_op_movl_T1_o7, gen_op_movl_T1_l0, gen_op_movl_T1_l1, gen_op_movl_T1_l2, gen_op_movl_T1_l3, gen_op_movl_T1_l4, gen_op_movl_T1_l5, gen_op_movl_T1_l6, gen_op_movl_T1_l7, gen_op_movl_T1_i0, gen_op_movl_T1_i1, gen_op_movl_T1_i2, gen_op_movl_T1_i3, gen_op_movl_T1_i4, gen_op_movl_T1_i5, gen_op_movl_T1_i6, gen_op_movl_T1_i7, }, { gen_op_movl_T2_g0, gen_op_movl_T2_g1, gen_op_movl_T2_g2, gen_op_movl_T2_g3, gen_op_movl_T2_g4, gen_op_movl_T2_g5, gen_op_movl_T2_g6, gen_op_movl_T2_g7, gen_op_movl_T2_o0, gen_op_movl_T2_o1, gen_op_movl_T2_o2, gen_op_movl_T2_o3, gen_op_movl_T2_o4, gen_op_movl_T2_o5, gen_op_movl_T2_o6, gen_op_movl_T2_o7, gen_op_movl_T2_l0, gen_op_movl_T2_l1, gen_op_movl_T2_l2, gen_op_movl_T2_l3, gen_op_movl_T2_l4, gen_op_movl_T2_l5, gen_op_movl_T2_l6, gen_op_movl_T2_l7, gen_op_movl_T2_i0, gen_op_movl_T2_i1, gen_op_movl_T2_i2, gen_op_movl_T2_i3, gen_op_movl_T2_i4, gen_op_movl_T2_i5, gen_op_movl_T2_i6, gen_op_movl_T2_i7, }};static GenOpFunc1 *gen_op_movl_TN_im[3] = { gen_op_movl_T0_im, gen_op_movl_T1_im, gen_op_movl_T2_im};// Sign extending versionstatic GenOpFunc1 * const gen_op_movl_TN_sim[3] = { gen_op_movl_T0_sim, gen_op_movl_T1_sim, gen_op_movl_T2_sim};#ifdef TARGET_SPARC64#define GEN32(func, NAME) \static GenOpFunc *NAME ## _table [64] = { \NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \NAME ## 32, 0, NAME ## 34, 0, NAME ## 36, 0, NAME ## 38, 0, \NAME ## 40, 0, NAME ## 42, 0, NAME ## 44, 0, NAME ## 46, 0, \NAME ## 48, 0, NAME ## 50, 0, NAME ## 52, 0, NAME ## 54, 0, \NAME ## 56, 0, NAME ## 58, 0, NAME ## 60, 0, NAME ## 62, 0, \}; \static inline void func(int n) \{ \ NAME ## _table[n](); \}#else#define GEN32(func, NAME) \static GenOpFunc *NAME ## _table [32] = { \NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \}; \static inline void func(int n) \{ \ NAME ## _table[n](); \}#endif/* floating point registers moves */GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fprf);GEN32(gen_op_load_fpr_FT1, gen_op_load_fpr_FT1_fprf);GEN32(gen_op_store_FT0_fpr, gen_op_store_FT0_fpr_fprf);GEN32(gen_op_store_FT1_fpr, gen_op_store_FT1_fpr_fprf);GEN32(gen_op_load_fpr_DT0, gen_op_load_fpr_DT0_fprf);GEN32(gen_op_load_fpr_DT1, gen_op_load_fpr_DT1_fprf);GEN32(gen_op_store_DT0_fpr, gen_op_store_DT0_fpr_fprf);GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_fpr_fprf);#ifdef TARGET_SPARC64// 'a' versions allowed to user depending on asi#if defined(CONFIG_USER_ONLY)#define supervisor(dc) 0#define gen_op_ldst(name) gen_op_##name##_raw()#define OP_LD_TABLE(width) \ static void gen_op_##width##a(int insn, int is_ld, int size, int sign) \ { \ int asi, offset; \ \ if (IS_IMM) { \ offset = GET_FIELD(insn, 25, 31); \ if (is_ld) \ gen_op_ld_asi_reg(offset, size, sign); \ else \ gen_op_st_asi_reg(offset, size, sign); \ return; \ } \ asi = GET_FIELD(insn, 19, 26); \ switch (asi) { \ case 0x80: /* Primary address space */ \ gen_op_##width##_raw(); \ break; \ default: \ break; \ } \ }#else#define gen_op_ldst(name) (*gen_op_##name[dc->mem_idx])()#define OP_LD_TABLE(width) \ static GenOpFunc *gen_op_##width[] = { \ &gen_op_##width##_user, \ &gen_op_##width##_kernel, \ }; \ \ static void gen_op_##width##a(int insn, int is_ld, int size, int sign) \ { \ int asi, offset; \ \ if (IS_IMM) { \ offset = GET_FIELD(insn, 25, 31); \ if (is_ld) \ gen_op_ld_asi_reg(offset, size, sign); \ else \ gen_op_st_asi_reg(offset, size, sign); \ return; \ } \ asi = GET_FIELD(insn, 19, 26); \ if (is_ld) \ gen_op_ld_asi(asi, size, sign); \ else \ gen_op_st_asi(asi, size, sign); \ }#define supervisor(dc) (dc->mem_idx == 1)#endif#else#if defined(CONFIG_USER_ONLY)#define gen_op_ldst(name) gen_op_##name##_raw()#define OP_LD_TABLE(width)#define supervisor(dc) 0#else#define gen_op_ldst(name) (*gen_op_##name[dc->mem_idx])()#define OP_LD_TABLE(width) \static GenOpFunc *gen_op_##width[] = { \ &gen_op_##width##_user, \ &gen_op_##width##_kernel, \}; \ \static void gen_op_##width##a(int insn, int is_ld, int size, int sign) \{ \ int asi; \ \ asi = GET_FIELD(insn, 19, 26); \ switch (asi) { \ case 10: /* User data access */ \ gen_op_##width##_user(); \ break; \ case 11: /* Supervisor data access */ \ gen_op_##width##_kernel(); \ break; \ case 0x20 ... 0x2f: /* MMU passthrough */ \ if (is_ld) \ gen_op_ld_asi(asi, size, sign); \ else \ gen_op_st_asi(asi, size, sign); \ break; \ default: \ if (is_ld) \ gen_op_ld_asi(asi, size, sign); \ else \ gen_op_st_asi(asi, size, sign); \ break; \ } \}#define supervisor(dc) (dc->mem_idx == 1)#endif#endifOP_LD_TABLE(ld);OP_LD_TABLE(st);OP_LD_TABLE(ldub);OP_LD_TABLE(lduh);OP_LD_TABLE(ldsb);OP_LD_TABLE(ldsh);OP_LD_TABLE(stb);OP_LD_TABLE(sth);OP_LD_TABLE(std);OP_LD_TABLE(ldstub);OP_LD_TABLE(swap);OP_LD_TABLE(ldd);OP_LD_TABLE(stf);OP_LD_TABLE(stdf);OP_LD_TABLE(ldf);OP_LD_TABLE(lddf);#ifdef TARGET_SPARC64OP_LD_TABLE(ldsw);OP_LD_TABLE(ldx);OP_LD_TABLE(stx);OP_LD_TABLE(cas);OP_LD_TABLE(casx);#endifstatic inline void gen_movl_imm_TN(int reg, uint32_t imm){ gen_op_movl_TN_im[reg](imm);}static inline void gen_movl_imm_T1(uint32_t val){ gen_movl_imm_TN(1, val);}static inline void gen_movl_imm_T0(uint32_t val){ gen_movl_imm_TN(0, val);}static inline void gen_movl_simm_TN(int reg, int32_t imm){ gen_op_movl_TN_sim[reg](imm);}static inline void gen_movl_simm_T1(int32_t val){ gen_movl_simm_TN(1, val);}static inline void gen_movl_simm_T0(int32_t val){ gen_movl_simm_TN(0, val);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -