📄 translate.c.svn-base
字号:
/* * Alpha emulation cpu translation for qemu. * * Copyright (c) 2007 Jocelyn Mayer * * 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 */#include <stdint.h>#include <stdlib.h>#include <stdio.h>#include "cpu.h"#include "exec-all.h"#include "disas.h"#define DO_SINGLE_STEP#define GENERATE_NOP#define ALPHA_DEBUG_DISAS#define DO_TB_FLUSHtypedef struct DisasContext DisasContext;struct DisasContext { uint64_t pc; int mem_idx;#if !defined (CONFIG_USER_ONLY) int pal_mode;#endif uint32_t amask;};#ifdef USE_DIRECT_JUMP#define TBPARAM(x)#else#define TBPARAM(x) (long)(x)#endifenum {#define DEF(s, n, copy_size) INDEX_op_ ## s,#include "opc.h"#undef DEF NB_OPS,};static uint16_t *gen_opc_ptr;static uint32_t *gen_opparam_ptr;#include "gen-op.h"static always_inline void gen_op_nop (void){#if defined(GENERATE_NOP) gen_op_no_op();#endif}#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 always_inline void func (int n) \{ \ NAME ## _table[n](); \}/* IR moves *//* Special hacks for ir31 */#define gen_op_load_T0_ir31 gen_op_reset_T0#define gen_op_load_T1_ir31 gen_op_reset_T1#define gen_op_load_T2_ir31 gen_op_reset_T2#define gen_op_store_T0_ir31 gen_op_nop#define gen_op_store_T1_ir31 gen_op_nop#define gen_op_store_T2_ir31 gen_op_nop#define gen_op_cmov_ir31 gen_op_nopGEN32(gen_op_load_T0_ir, gen_op_load_T0_ir);GEN32(gen_op_load_T1_ir, gen_op_load_T1_ir);GEN32(gen_op_load_T2_ir, gen_op_load_T2_ir);GEN32(gen_op_store_T0_ir, gen_op_store_T0_ir);GEN32(gen_op_store_T1_ir, gen_op_store_T1_ir);GEN32(gen_op_store_T2_ir, gen_op_store_T2_ir);GEN32(gen_op_cmov_ir, gen_op_cmov_ir);static always_inline void gen_load_ir (DisasContext *ctx, int irn, int Tn){ switch (Tn) { case 0: gen_op_load_T0_ir(irn); break; case 1: gen_op_load_T1_ir(irn); break; case 2: gen_op_load_T2_ir(irn); break; }}static always_inline void gen_store_ir (DisasContext *ctx, int irn, int Tn){ switch (Tn) { case 0: gen_op_store_T0_ir(irn); break; case 1: gen_op_store_T1_ir(irn); break; case 2: gen_op_store_T2_ir(irn); break; }}/* FIR moves *//* Special hacks for fir31 */#define gen_op_load_FT0_fir31 gen_op_reset_FT0#define gen_op_load_FT1_fir31 gen_op_reset_FT1#define gen_op_load_FT2_fir31 gen_op_reset_FT2#define gen_op_store_FT0_fir31 gen_op_nop#define gen_op_store_FT1_fir31 gen_op_nop#define gen_op_store_FT2_fir31 gen_op_nop#define gen_op_cmov_fir31 gen_op_nopGEN32(gen_op_load_FT0_fir, gen_op_load_FT0_fir);GEN32(gen_op_load_FT1_fir, gen_op_load_FT1_fir);GEN32(gen_op_load_FT2_fir, gen_op_load_FT2_fir);GEN32(gen_op_store_FT0_fir, gen_op_store_FT0_fir);GEN32(gen_op_store_FT1_fir, gen_op_store_FT1_fir);GEN32(gen_op_store_FT2_fir, gen_op_store_FT2_fir);GEN32(gen_op_cmov_fir, gen_op_cmov_fir);static always_inline void gen_load_fir (DisasContext *ctx, int firn, int Tn){ switch (Tn) { case 0: gen_op_load_FT0_fir(firn); break; case 1: gen_op_load_FT1_fir(firn); break; case 2: gen_op_load_FT2_fir(firn); break; }}static always_inline void gen_store_fir (DisasContext *ctx, int firn, int Tn){ switch (Tn) { case 0: gen_op_store_FT0_fir(firn); break; case 1: gen_op_store_FT1_fir(firn); break; case 2: gen_op_store_FT2_fir(firn); break; }}/* Memory moves */#if defined(CONFIG_USER_ONLY)#define OP_LD_TABLE(width) \static GenOpFunc *gen_op_ld##width[] = { \ &gen_op_ld##width##_raw, \}#define OP_ST_TABLE(width) \static GenOpFunc *gen_op_st##width[] = { \ &gen_op_st##width##_raw, \}#else#define OP_LD_TABLE(width) \static GenOpFunc *gen_op_ld##width[] = { \ &gen_op_ld##width##_kernel, \ &gen_op_ld##width##_executive, \ &gen_op_ld##width##_supervisor, \ &gen_op_ld##width##_user, \}#define OP_ST_TABLE(width) \static GenOpFunc *gen_op_st##width[] = { \ &gen_op_st##width##_kernel, \ &gen_op_st##width##_executive, \ &gen_op_st##width##_supervisor, \ &gen_op_st##width##_user, \}#endif#define GEN_LD(width) \OP_LD_TABLE(width); \static always_inline void gen_ld##width (DisasContext *ctx) \{ \ (*gen_op_ld##width[ctx->mem_idx])(); \}#define GEN_ST(width) \OP_ST_TABLE(width); \static always_inline void gen_st##width (DisasContext *ctx) \{ \ (*gen_op_st##width[ctx->mem_idx])(); \}GEN_LD(bu);GEN_ST(b);GEN_LD(wu);GEN_ST(w);GEN_LD(l);GEN_ST(l);GEN_LD(q);GEN_ST(q);GEN_LD(q_u);GEN_ST(q_u);GEN_LD(l_l);GEN_ST(l_c);GEN_LD(q_l);GEN_ST(q_c);#if 0 /* currently unused */GEN_LD(f);GEN_ST(f);GEN_LD(g);GEN_ST(g);#endif /* 0 */GEN_LD(s);GEN_ST(s);GEN_LD(t);GEN_ST(t);#if defined(__i386__) || defined(__x86_64__)static always_inline void gen_op_set_s16_T0 (int16_t imm){ gen_op_set_s32_T0((int32_t)imm);}static always_inline void gen_op_set_s16_T1 (int16_t imm){ gen_op_set_s32_T1((int32_t)imm);}static always_inline void gen_op_set_u16_T0 (uint16_t imm){ gen_op_set_s32_T0((uint32_t)imm);}static always_inline void gen_op_set_u16_T1 (uint16_t imm){ gen_op_set_s32_T1((uint32_t)imm);}#endifstatic always_inline void gen_set_sT0 (DisasContext *ctx, int64_t imm){ int32_t imm32; int16_t imm16; imm32 = imm; if (imm32 == imm) { imm16 = imm; if (imm16 == imm) { if (imm == 0) { gen_op_reset_T0(); } else { gen_op_set_s16_T0(imm16); } } else { gen_op_set_s32_T0(imm32); } } else {#if 0 // Qemu does not know how to do this... gen_op_set_64_T0(imm);#else gen_op_set_64_T0(imm >> 32, imm);#endif }}static always_inline void gen_set_sT1 (DisasContext *ctx, int64_t imm){ int32_t imm32; int16_t imm16; imm32 = imm; if (imm32 == imm) { imm16 = imm; if (imm16 == imm) { if (imm == 0) { gen_op_reset_T1(); } else { gen_op_set_s16_T1(imm16); } } else { gen_op_set_s32_T1(imm32); } } else {#if 0 // Qemu does not know how to do this... gen_op_set_64_T1(imm);#else gen_op_set_64_T1(imm >> 32, imm);#endif }}static always_inline void gen_set_uT0 (DisasContext *ctx, uint64_t imm){ if (!(imm >> 32)) { if ((!imm >> 16)) { if (imm == 0) gen_op_reset_T0(); else gen_op_set_u16_T0(imm); } else { gen_op_set_u32_T0(imm); } } else {#if 0 // Qemu does not know how to do this... gen_op_set_64_T0(imm);#else gen_op_set_64_T0(imm >> 32, imm);#endif }}static always_inline void gen_set_uT1 (DisasContext *ctx, uint64_t imm){ if (!(imm >> 32)) { if ((!imm >> 16)) { if (imm == 0) gen_op_reset_T1(); else gen_op_set_u16_T1(imm); } else { gen_op_set_u32_T1(imm); } } else {#if 0 // Qemu does not know how to do this... gen_op_set_64_T1(imm);#else gen_op_set_64_T1(imm >> 32, imm);#endif }}static always_inline void gen_update_pc (DisasContext *ctx){ if (!(ctx->pc >> 32)) { gen_op_update_pc32(ctx->pc); } else {#if 0 // Qemu does not know how to do this... gen_op_update_pc(ctx->pc);#else gen_op_update_pc(ctx->pc >> 32, ctx->pc);#endif }}static always_inline void _gen_op_bcond (DisasContext *ctx){#if 0 // Qemu does not know how to do this... gen_op_bcond(ctx->pc);#else gen_op_bcond(ctx->pc >> 32, ctx->pc);#endif}static always_inline void gen_excp (DisasContext *ctx, int exception, int error_code){ gen_update_pc(ctx); gen_op_excp(exception, error_code);}static always_inline void gen_invalid (DisasContext *ctx){ printf("gen_invalid\n");//debugger gen_excp(ctx, EXCP_OPCDEC, 0);}static always_inline void gen_load_mem (DisasContext *ctx, void (*gen_load_op)(DisasContext *ctx), int ra, int rb, int32_t disp16, int clear){ if (ra == 31 && disp16 == 0) { /* UNOP */ gen_op_nop(); } else { gen_load_ir(ctx, rb, 0); if (disp16 != 0) { gen_set_sT1(ctx, disp16); gen_op_addq(); } if (clear) gen_op_n7(); (*gen_load_op)(ctx); gen_store_ir(ctx, ra, 1); }}static always_inline void gen_store_mem (DisasContext *ctx, void (*gen_store_op)(DisasContext *ctx), int ra, int rb, int32_t disp16, int clear){ gen_load_ir(ctx, rb, 0); if (disp16 != 0) { gen_set_sT1(ctx, disp16); gen_op_addq(); } if (clear) gen_op_n7(); gen_load_ir(ctx, ra, 1); (*gen_store_op)(ctx);}static always_inline void gen_load_fmem (DisasContext *ctx, void (*gen_load_fop)(DisasContext *ctx), int ra, int rb, int32_t disp16){ gen_load_ir(ctx, rb, 0); if (disp16 != 0) { gen_set_sT1(ctx, disp16); gen_op_addq(); } (*gen_load_fop)(ctx); gen_store_fir(ctx, ra, 1);}static always_inline void gen_store_fmem (DisasContext *ctx, void (*gen_store_fop)(DisasContext *ctx), int ra, int rb, int32_t disp16){ gen_load_ir(ctx, rb, 0); if (disp16 != 0) { gen_set_sT1(ctx, disp16); gen_op_addq(); } gen_load_fir(ctx, ra, 1); (*gen_store_fop)(ctx);}static always_inline void gen_bcond (DisasContext *ctx, void (*gen_test_op)(void), int ra, int32_t disp16){ if (disp16 != 0) { gen_set_uT0(ctx, ctx->pc); gen_set_sT1(ctx, disp16 << 2); gen_op_addq1(); } else { gen_set_uT1(ctx, ctx->pc); } gen_load_ir(ctx, ra, 0); (*gen_test_op)(); _gen_op_bcond(ctx);}static always_inline void gen_fbcond (DisasContext *ctx, void (*gen_test_op)(void), int ra, int32_t disp16){ if (disp16 != 0) { gen_set_uT0(ctx, ctx->pc); gen_set_sT1(ctx, disp16 << 2); gen_op_addq1(); } else { gen_set_uT1(ctx, ctx->pc); } gen_load_fir(ctx, ra, 0); (*gen_test_op)(); _gen_op_bcond(ctx);}static always_inline void gen_arith2 (DisasContext *ctx, void (*gen_arith_op)(void), int rb, int rc, int islit, int8_t lit){ if (islit) gen_set_sT0(ctx, lit); else gen_load_ir(ctx, rb, 0); (*gen_arith_op)(); gen_store_ir(ctx, rc, 0);}static always_inline void gen_arith3 (DisasContext *ctx, void (*gen_arith_op)(void), int ra, int rb, int rc, int islit, int8_t lit){ gen_load_ir(ctx, ra, 0); if (islit) gen_set_sT1(ctx, lit); else gen_load_ir(ctx, rb, 1); (*gen_arith_op)(); gen_store_ir(ctx, rc, 0);}static always_inline void gen_cmov (DisasContext *ctx, void (*gen_test_op)(void), int ra, int rb, int rc, int islit, int8_t lit){ gen_load_ir(ctx, ra, 1); if (islit) gen_set_sT0(ctx, lit); else gen_load_ir(ctx, rb, 0); (*gen_test_op)(); gen_op_cmov_ir(rc);}static always_inline void gen_farith2 (DisasContext *ctx, void (*gen_arith_fop)(void), int rb, int rc){ gen_load_fir(ctx, rb, 0); (*gen_arith_fop)();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -