📄 koala.hh
字号:
int wired = cp0[Wired]; int free = tlb_size - wired; return (tlb_size - 1 - wired + (now - random_seed)) % free + wired; } // An ASID is represented by a 16 bit integer that is either a positive // (non-zero) ASID, complemented if the G bit is also set. asid_match() // checks two ASIDs for equivalence. Yet another demonstration of the // versatility of exclusive-or. ;) static bool asid_match(Int16 asid1, Int16 asid2) { return (asid1 ^ asid2) <= 0; } // Operations on the TLB lookup map. The map is a hash table indexed by a // hash value computed from the ASID and the bits of virtual page number // unaffected by any page mask. The result of the map lookup is a TLB // entry. The hash function doesn't provide an ideal distribution, but as // a minimum, it maintains a separate hash chain per ASID, and provides // good distribution at least for sparse address spaces. The hash table // always has an extra entry pointing to an invalid page. static int tlb_hash(VA va) { return (bits(va, 63, 25) % tlb_map_size); } static bool va_match(VA va1, VA va2, VA mask) { return !((va1 ^ va2) & mask); } // I-cache buffer operations. static bool ibuf_match(VA va, VA tag) { return ((va >> log2_icache_line) ^ tag) == 0; } // TLB operations. void reset_tlb(); void dump_tlb(); TLBEntry* probe_tlb(VA va); void set_tlb_entry(int index); PA translate_vaddr(VA va, int type); // Instruction cache operations. void reset_icache(); void control_icache(VA va, PA pa, int op, int type); Instr fetch(VA va, PA pa); // Data cache operations. void reset_dcache(); void control_dcache(VA va, PA pa, int op, int type); template <int syscmd> UInt64 load(VA va, PA pa); // data load template <int syscmd> void store(UInt64 x, VA va, PA pa); // data store UInt64 load_left(UInt64 x, VA va, int syscmd); // LDL, LWL UInt64 load_right(UInt64 x, VA va, int syscmd); // LDR, LWR void store_left(UInt64 x, VA va, int syscmd); // SDL, SWL void store_right(UInt64 x, VA va, int syscmd); // SDR, SWR // Complete any pending memory operations. void sync(); // Some state information constants. bool allow_xinstr() const { return mode & (kmode|xmode); } bool branch_delay_slot() const { return pipeline == branch_delay; } // Exception operations. process_exception() sets the simulator state up // for the exception handler as specified by 'cause' and 'vec'. // process_reset() processes a reset exception as specified by the // (events) word. All other functions handle particular exceptions by // calling process_exception() after setting any exception-specific // parameters. Most of them never return as they longjmp to the start of // the pipeline. void process_reset(); void process_exception(UInt32 cause, int vec); void process_address_error(int type, VA va) { int exc = (type == data_store) ? EXC_AdES : EXC_AdEL; cp0[BadVAddr] = va; process_exception(exc, common_vector); } void process_tlb_refill(int type, VA va, bool x) { int exc = (type == data_store) ? EXC_TLBS : EXC_TLBL; int vec = (bit(cp0[SR], SR_EXL)) ? common_vector : (x) ? xtlb_refill_vector : tlb_refill_vector; cp0[BadVAddr] = va; cp0[Context] = set_bits(cp0[Context], bits(cp0[BadVAddr], 31, 13), 22, 4); VA badvpn2 = (bits(va, 63, 62) << 31) | bits(va, 39, 13); cp0[XContext] = set_bits(cp0[XContext], badvpn2, 32, 4); cp0[EntryHi] = (va & (bitmask(63,62) | bitmask(39, 13))) | bits(asid, 7, 0); process_exception(exc, vec); } void process_tlb_invalid(int type, VA va) { int exc = (type == data_store) ? EXC_TLBS : EXC_TLBL; cp0[BadVAddr] = va; cp0[Context] = set_bits(cp0[Context], bits(cp0[BadVAddr], 31, 13), 22, 4); VA badvpn2 = (bits(va, 63, 62) << 31) | bits(va, 39, 13); if (trace_level >= print_instructions) { log("TLB Invalid: %p", va); dump_tlb(); } cp0[XContext] = set_bits(cp0[XContext], badvpn2, 32, 4); cp0[EntryHi] = (va & (bitmask(63,62) | bitmask(39, 13))) | bits(asid, 7, 0); process_exception(exc, common_vector); } void process_tlb_modified(VA va) { cp0[BadVAddr] = va; cp0[Context] = set_bits(cp0[Context], bits(cp0[BadVAddr], 31, 13), 22, 4); VA badvpn2 = (bits(va, 63, 62) << 31) | bits(va, 39, 13); if (trace_level >= print_instructions) { log("Modified: %p\n", va); dump_tlb(); } cp0[XContext] = set_bits(cp0[XContext], badvpn2, 32, 4); cp0[EntryHi] = (va & (bitmask(63,62) | bitmask(39, 13))) | bits(asid, 7, 0); process_exception(EXC_Mod, common_vector); } void process_bus_error(int type) { int exc = (type == instr_fetch) ? EXC_IBE : EXC_DBE; process_exception(exc, common_vector); } void process_integer_overflow() { process_exception(EXC_Ov, common_vector); } void process_trap() { process_exception(EXC_Tr, common_vector); } void process_syscall() { process_exception(EXC_Sys, common_vector); } void process_breakpoint() { process_exception(EXC_Bp, common_vector); } void process_reserved_instruction() { process_exception(EXC_RI, common_vector); } void process_coprocessor_unusable(int c) { process_exception(EXC_CpU | (c << (Cause_CE_First)), common_vector); } void process_fp_exception() { process_exception(EXC_FPE, common_vector); } void process_interrupt() { process_exception(EXC_Int, common_vector); } // Endianess parameters. The data received from the memory bus is always // in the host byte order, and uses host byte addressing. bool big_endian_mem() const { return bit(cp0[Config], Config_BE); } bool reverse_endian() const { return mode & rmode; } bool big_endian_cpu() const { return mode & bmode; } // Helper used to extract data from a memory cell, taking into account // current endianess. template <int syscmd> typename FixedWidth<(syscmd + 1) * 8>::Unsigned swizzle(UInt64 x, unsigned addr) const { if (syscmd == word) { // Optimization for instruction fetches. UInt32 y = (((big_endian_cpu() << 2) ^ addr) & 7) ? x >> 32 : x; return reverse_endian() ? byte_swap(y) : y; } else if (syscmd == doubleword) { // Optimization for doublewords, assuming (addr & 7) == 0. return reverse_endian() ? byte_swap(x) : x; } else { // Generic implementation for all other types. typedef typename FixedWidth<(syscmd + 1) * 8>::Unsigned T; int shift = big_endian_cpu() ? (64 - IntTraits<T>::width) - (addr & 7) * 8 : (addr & 7) * 8; T y = x >> shift; return reverse_endian() ? byte_swap(y) : y; } } // Helper used to fix an address for a given type. template <int syscmd> PA swizzle(PA pa) const {#if 0 const PA mask = (syscmd == byte ? bitmask(2, 0) : syscmd == halfword ? bitmask(2, 1) : syscmd == word ? bitmask(2, 2) : 0); return (big_endian_cpu() == big_endian_host()) ? pa : pa ^ mask;#endif return pa; } // Set the Coprocessor 0 timer interrupt. void set_timer(); // Coprocessor 0 register access. This is necessary as some registers // are computed on demand, and most registers have some read-only fields. UInt64 read_cp0(int n) const; void write_cp0(int n, UInt64 x); // Coprocessor 1 (FPU) simulator: // Floating point condition names static const char* condname[16]; enum { FCR0 = 0, FP_Rev_Last = 7, FP_Rev_First = 0, FP_Imp_Last = 15, FP_Imp_First = 8, FCR31 = 31, FP_RM_Last = 1, FP_RM_First = 0, FP_Flag_Last = 6, FP_Flag_First = 2, FP_Enable_Last = 11, FP_Enable_First = 7, FP_Cause_Last = 17, FP_Cause_First = 12, FP_C = 23, FP_FS = 24 }; // Software IEC/IEEE floating-point rounding mode. enum { float_round_nearest_even = 0, float_round_to_zero = 1, float_round_up = 2, float_round_down = 3 }; // Software IEC/IEEE floating-point exception flags. enum { float_flag_inexact = 1, float_flag_underflow = 2, float_flag_overflow = 4, float_flag_divbyzero = 8, float_flag_invalid = 16, float_flag_unimplemented = 32 }; int float_rounding_mode() const { return bits(cp1[FCR31], FP_RM_Last, FP_RM_First); } float convert_from_s(UInt32 value) const { return *(float *)(&value); } double convert_from_d(UInt64 value) { return *(double *)(&value); } UInt32 convert_to_s(float value) { return *(UInt32 *)(&value); } UInt64 convert_to_d(double value) { return *(UInt64 *)(&value); } int decode_cop1_s(Instr instr); int decode_cop1_d(Instr instr); int decode_cop1_w(Instr instr); int decode_cop1_l(Instr instr); // The main instruction decoder with satelite functions for some of the // more elaborate instructions. int decode(Instr instr); int decode_cop0(Instr instr); int decode_cop1(Instr instr); int decode_cache(Instr instr); int decode_ldc1(Instr instr); int decode_lwc1(Instr instr); int decode_sdc1(Instr instr); int decode_swc1(Instr instr); // Some debugging help. void dump_gpr_registers() const; void dump_fpr_registers() const;private: // Finally, some configuration data. struct { char* bus; int ec; char* ep; int be; int trace; } conf;};#endif // koala_hh_included
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -