📄 pisa.h
字号:
/* #else *//* lwl/swl stuff */#define WL_SIZE(ADDR) ((ADDR) & 0x03)#define WL_BASE(ADDR) ((ADDR) & ~0x03)#define WL_PROT_MASK1(ADDR) (md_lr_masks[WL_SIZE(ADDR)])#define WL_PROT_MASK2(ADDR) (md_lr_masks[4-WL_SIZE(ADDR)])/* lwr/swr stuff */#define WR_SIZE(ADDR) (((ADDR) & 0x03)+1)#define WR_BASE(ADDR) ((ADDR) & ~0x03)#define WR_PROT_MASK1(ADDR) ((md_lr_masks[WR_SIZE(ADDR)]))#define WR_PROT_MASK2(ADDR) (md_lr_masks[4-WR_SIZE(ADDR)])#endif/* * various other helper macros/functions *//* non-zero if system call is an exit() */#define SS_SYS_exit 1#define MD_EXIT_SYSCALL(REGS) ((REGS)->regs_R[2] == SS_SYS_exit)/* non-zero if system call is a write to stdout/stderr */#define SS_SYS_write 4#define MD_OUTPUT_SYSCALL(REGS) \ ((REGS)->regs_R[2] == SS_SYS_write \ && ((REGS)->regs_R[4] == /* stdout */1 \ || (REGS)->regs_R[4] == /* stderr */2))/* returns stream of an output system call, translated to host */#define MD_STREAM_FILENO(REGS) ((REGS)->regs_R[4])/* returns non-zero if instruction is a function call */#define MD_IS_CALL(OP) \ ((MD_OP_FLAGS(OP) & (F_CTRL|F_CALL)) == (F_CTRL|F_CALL))/* returns non-zero if instruction is a function return */#define MD_IS_RETURN(OP) ((OP) == JR && (RS) == 31)/* returns non-zero if instruction is an indirect jump */#define MD_IS_INDIR(OP) ((OP) == JR)/* addressing mode probe, enums and strings */enum md_amode_type { md_amode_imm, /* immediate addressing mode */ md_amode_gp, /* global data access through global pointer */ md_amode_sp, /* stack access through stack pointer */ md_amode_fp, /* stack access through frame pointer */ md_amode_disp, /* (reg + const) addressing */ md_amode_rr, /* (reg + reg) addressing */ md_amode_NUM};extern char *md_amode_str[md_amode_NUM];/* addressing mode pre-probe FSM, must see all instructions */#define MD_AMODE_PREPROBE(OP, FSM) \ { if ((OP) == LUI) (FSM) = (RT); }/* compute addressing mode, only for loads/stores */#define MD_AMODE_PROBE(AM, OP, FSM) \ { \ if (MD_OP_FLAGS(OP) & F_DISP) \ { \ if ((BS) == (FSM)) \ (AM) = md_amode_imm; \ else if ((BS) == MD_REG_GP) \ (AM) = md_amode_gp; \ else if ((BS) == MD_REG_SP) \ (AM) = md_amode_sp; \ else if ((BS) == MD_REG_FP) /* && bind_to_seg(addr) == seg_stack */\ (AM) = md_amode_fp; \ else \ (AM) = md_amode_disp; \ } \ else if (MD_OP_FLAGS(OP) & F_RR) \ (AM) = md_amode_rr; \ else \ panic("cannot decode addressing mode"); \ }/* addressing mode pre-probe FSM, after all loads and stores */#define MD_AMODE_POSTPROBE(FSM) \ { (FSM) = MD_REG_ZERO; }/* * EIO package configuration/macros *//* expected EIO file format */#define MD_EIO_FILE_FORMAT EIO_PISA_FORMAT#define MD_MISC_REGS_TO_EXO(REGS) \ exo_new(ec_list, \ /*icnt*/exo_new(ec_integer, (exo_integer_t)sim_num_insn), \ /*PC*/exo_new(ec_address, (exo_integer_t)(REGS)->regs_PC), \ /*NPC*/exo_new(ec_address, (exo_integer_t)(REGS)->regs_NPC), \ /*HI*/exo_new(ec_integer, (exo_integer_t)(REGS)->regs_C.hi), \ /*LO*/exo_new(ec_integer, (exo_integer_t)(REGS)->regs_C.lo), \ /*FCC*/exo_new(ec_integer, (exo_integer_t)(REGS)->regs_C.fcc),\ NULL)#define MD_IREG_TO_EXO(REGS, IDX) \ exo_new(ec_address, (exo_integer_t)(REGS)->regs_R[IDX])#define MD_FREG_TO_EXO(REGS, IDX) \ exo_new(ec_address, (exo_integer_t)(REGS)->regs_F.l[IDX])#define MD_EXO_TO_MISC_REGS(EXO, ICNT, REGS) \ /* check EXO format for errors... */ \ if (!exo \ || exo->ec != ec_list \ || !exo->as_list.head \ || exo->as_list.head->ec != ec_integer \ || !exo->as_list.head->next \ || exo->as_list.head->next->ec != ec_address \ || !exo->as_list.head->next->next \ || exo->as_list.head->next->next->ec != ec_address \ || !exo->as_list.head->next->next->next \ || exo->as_list.head->next->next->next->ec != ec_integer \ || !exo->as_list.head->next->next->next->next \ || exo->as_list.head->next->next->next->next->ec != ec_integer \ || !exo->as_list.head->next->next->next->next->next \ || exo->as_list.head->next->next->next->next->next->ec != ec_integer\ || exo->as_list.head->next->next->next->next->next->next != NULL) \ fatal("could not read EIO misc regs"); \ (ICNT) = (counter_t)exo->as_list.head->as_integer.val; \ (REGS)->regs_PC = (md_addr_t)exo->as_list.head->next->as_address.val; \ (REGS)->regs_NPC = \ (md_addr_t)exo->as_list.head->next->next->as_address.val; \ (REGS)->regs_C.hi = \ (word_t)exo->as_list.head->next->next->next->as_integer.val; \ (REGS)->regs_C.lo = \ (word_t)exo->as_list.head->next->next->next->next->as_integer.val; \ (REGS)->regs_C.fcc = \ (int)exo->as_list.head->next->next->next->next->next->as_integer.val;#define MD_EXO_TO_IREG(EXO, REGS, IDX) \ ((REGS)->regs_R[IDX] = (word_t)(EXO)->as_integer.val)#define MD_EXO_TO_FREG(EXO, REGS, IDX) \ ((REGS)->regs_F.l[IDX] = (word_t)(EXO)->as_integer.val)#define MD_EXO_CMP_IREG(EXO, REGS, IDX) \ ((REGS)->regs_R[IDX] != (sword_t)(EXO)->as_integer.val)#define MD_FIRST_IN_REG 2#define MD_LAST_IN_REG 7#define MD_FIRST_OUT_REG 2#define MD_LAST_OUT_REG 7/* * configure the EXO package *//* EXO pointer class */typedef qword_t exo_address_t;/* EXO integer class, 64-bit encoding */typedef qword_t exo_integer_t;/* EXO floating point class, 64-bit encoding */typedef double exo_float_t;/* * configure the stats package *//* counter stats */#ifdef HOST_HAS_QWORD#define stat_reg_counter stat_reg_sqword#define sc_counter sc_sqword#define for_counter for_sqword#else /* !HOST_HAS_QWORD */#define stat_reg_counter stat_reg_double#define sc_counter sc_double#define for_counter for_double#endif /* HOST_HAS_QWORD *//* address stats */#define stat_reg_addr stat_reg_uint/* * configure the DLite! debugger *//* register bank specifier */enum md_reg_type { rt_gpr, /* general purpose register */ rt_lpr, /* integer-precision floating pointer register */ rt_fpr, /* single-precision floating pointer register */ rt_dpr, /* double-precision floating pointer register */ rt_ctrl, /* control register */ rt_PC, /* program counter */ rt_NPC, /* next program counter */ rt_NUM};/* register name specifier */struct md_reg_names_t { char *str; /* register name */ enum md_reg_type file; /* register file */ int reg; /* register index */};/* symbolic register names, parser is case-insensitive */extern struct md_reg_names_t md_reg_names[];/* returns a register name string */char *md_reg_name(enum md_reg_type rt, int reg);/* default register accessor object */struct eval_value_t;struct regs_t;char * /* err str, NULL for no err */md_reg_obj(struct regs_t *regs, /* registers to access */ int is_write, /* access type */ enum md_reg_type rt, /* reg bank to probe */ int reg, /* register number */ struct eval_value_t *val); /* input, output *//* print integer REG(S) to STREAM */void md_print_ireg(md_gpr_t regs, int reg, FILE *stream);void md_print_iregs(md_gpr_t regs, FILE *stream);/* print floating point REG(S) to STREAM */void md_print_fpreg(md_fpr_t regs, int reg, FILE *stream);void md_print_fpregs(md_fpr_t regs, FILE *stream);/* print control REG(S) to STREAM */void md_print_creg(md_ctrl_t regs, int reg, FILE *stream);void md_print_cregs(md_ctrl_t regs, FILE *stream);/* compute CRC of all registers */word_t md_crc_regs(struct regs_t *regs);/* xor checksum registers */word_t md_xor_regs(struct regs_t *regs);/* * configure sim-outorder specifics *//* primitive operation used to compute addresses within pipeline */#define MD_AGEN_OP ADD/* NOP operation when injected into the pipeline */#define MD_NOP_OP NOP/* non-zero for a valid address, used to determine if speculative accesses should access the DL1 data cache */#define MD_VALID_ADDR(ADDR) \ (((ADDR) >= ld_text_base && (ADDR) < (ld_text_base + ld_text_size)) \ || ((ADDR) >= ld_data_base && (ADDR) < ld_stack_base))/* * configure branch predictors *//* shift used to ignore branch address least significant bits, usually log2(sizeof(md_inst_t)) */#define MD_BR_SHIFT 3 /* log2(8) *//* * target-dependent routines *//* intialize the inst decoder, this function builds the ISA decode tables */void md_init_decoder(void);/* disassemble an instruction */voidmd_print_insn(md_inst_t inst, /* instruction to disassemble */ md_addr_t pc, /* addr of inst, used for PC-rels */ FILE *stream); /* output stream */#endif /* PISA_H */#if 0/* virtual memory page size, this should be user configurable */#define SS_PAGE_SIZE 4096/* total number of registers in each register file (int and FP) */#define SS_NUM_REGS 32/* total number of register in processor 32I+32F+HI+LO+FCC+TMP+MEM+CTRL */#define SS_TOTAL_REGS \ (SS_NUM_REGS+SS_NUM_REGS+/*HI*/1+/*LO*/1+/*FCC*/1+/*TMP*/1+ \ /*MEM*/1+/*CTRL*/1)/* returns pre/post-incr/decr operation field value */#define SS_COMP_OP ((inst.a & 0xff00) >> 8)/* pre/post-incr/decr operation field specifiers */#define SS_COMP_NOP 0x00#define SS_COMP_POST_INC 0x01#define SS_COMP_POST_DEC 0x02#define SS_COMP_PRE_INC 0x03#define SS_COMP_PRE_DEC 0x04#define SS_COMP_POST_DBL_INC 0x05 /* for double word accesses */#define SS_COMP_POST_DBL_DEC 0x06#define SS_COMP_PRE_DBL_INC 0x07#define SS_COMP_PRE_DBL_DEC 0x08/* the instruction expression modifications required for an expression to support pre/post-incr/decr operations is accomplished by the INC_DEC() macro, it looks so contorted to reduce the control complexity of the equation (and thus reducing the compilation time greatly with GNU GCC - the key is to only emit EXPR one time) */#define INC_DEC(EXPR, REG, SIZE) \ (SET_GPR((REG), GPR(REG) + ss_fore_tab[(SIZE)-1][SS_COMP_OP]), \ (EXPR), \ SET_GPR((REG), GPR(REG) + ss_aft_tab[(SIZE)-1][SS_COMP_OP]))/* INC_DEC expression step tables, they map (operation, size) -> step value */extern int ss_fore_tab[8][5];extern int ss_aft_tab[8][5];/* pre-defined registers */#define Rgp 28 /* global data pointer */#define Rsp 29 /* stack pointer */#define Rfp 30 /* frame pointer *//* FIXME: non-reentrant LWL/LWR implementation workspace */extern SS_ADDR_TYPE ss_lr_temp;/* FIXME: non-reentrant temporary variables */extern SS_ADDR_TYPE temp_bs, temp_rd;/* instruction failure notification macro, this can be defined by the target simulator if, for example, the simulator wants to handle the instruction fault in a machine specific fashion; a string describing the instruction fault is passed to the IFAIL() macro */#ifndef IFAIL#define IFAIL(S) fatal(S)#endif /* IFAIL *//* check for divide by zero error, N is denom */#define DIV0(N) (((N) == 0) ? IFAIL("divide by 0") : (void)0)/* check reg specifier N for required double integer word alignment */#define INTALIGN(N) (((N) & 01) \ ? IFAIL("bad INT register alignment") : (void)0)/* check reg specifier N for required double FP word alignment */#define FPALIGN(N) (((N) & 01) \ ? IFAIL("bad FP register alignment") : (void)0)/* check target address TARG for required jump target alignment */#define TALIGN(TARG) (((TARG) & 0x7) \ ? IFAIL("bad jump alignment") : (void)0)/* inst checks disables, change all checks to NOP expressions */#define OVER(X,Y) ((void)0)#define UNDER(X,Y) ((void)0)#define DIV0(N) ((void)0)#define INTALIGN(N) ((void)0)#define FPALIGN(N) ((void)0)#define TALIGN(TARG) ((void)0)/* default division operator semantics, this operation is accessed through a macro because some simulators need to check for divide by zero faults before executing this operation */#define IDIV(A, B) ((A) / (B))#define IMOD(A, B) ((A) % (B))#define FDIV(A, B) ((A) / (B))#define FINT(A) ((int)A)#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -