/[gxemul]/trunk/src/include/cpu.h
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/src/include/cpu.h

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 14 by dpavlin, Mon Oct 8 16:18:51 2007 UTC revision 24 by dpavlin, Mon Oct 8 16:19:56 2007 UTC
# Line 2  Line 2 
2  #define CPU_H  #define CPU_H
3    
4  /*  /*
5   *  Copyright (C) 2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2005-2006  Anders Gavare.  All rights reserved.
6   *   *
7   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
8   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 28  Line 28 
28   *  SUCH DAMAGE.   *  SUCH DAMAGE.
29   *   *
30   *   *
31   *  $Id: cpu.h,v 1.48 2005/09/17 17:14:28 debug Exp $   *  $Id: cpu.h,v 1.75 2006/06/16 18:31:26 debug Exp $
32   *   *
33   *  See cpu.c.   *  CPU-related definitions.
34   */   */
35    
36    
# Line 38  Line 38 
38  #include <inttypes.h>  #include <inttypes.h>
39  #include <sys/time.h>  #include <sys/time.h>
40    
41  /*  This is needed for undefining 'mips' or 'ppc', on weird systems:  */  /*  This is needed for undefining 'mips', 'ppc' etc. on weird systems:  */
42  #include "../../config.h"  #include "../../config.h"
43    
44    /*
45     *  Dyntrans misc declarations, used throughout the dyntrans code.
46     *
47     *  Note that there is place for all instruction calls within a page,
48     *  and then 2 more. The first one of these "extra" instruction slots is
49     *  the end-of-page slot. It transfers control to the first instruction
50     *  slot on the next (virtual) page.
51     *
52     *  The second of these extra instruction slots is an additional
53     *  end-of-page slot for delay-slot architectures. On e.g. MIPS, a branch
54     *  instruction can "nullify" (skip) the delay-slot. If the end-of-page
55     *  slot is skipped, then we end up one step after that. That's where the
56     *  end_of_page2 slot is. :)
57     */
58    #define DYNTRANS_MISC_DECLARATIONS(arch,ARCH,addrtype)  struct \
59            arch ## _instr_call {                                   \
60                    void    (*f)(struct cpu *, struct arch ## _instr_call *); \
61                    size_t  arg[ARCH ## _N_IC_ARGS];                        \
62            };                                                              \
63                                                                            \
64            /*  Translation cache struct for each physical page:  */        \
65            struct arch ## _tc_physpage {                                   \
66                    struct arch ## _instr_call ics[ARCH ## _IC_ENTRIES_PER_PAGE+2];\
67                    uint32_t        next_ofs;       /*  (0 for end of chain)  */ \
68                    int             flags;                                  \
69                    addrtype        physaddr;                               \
70            };                                                              \
71                                                                            \
72            struct arch ## _vpg_tlb_entry {                                 \
73                    uint8_t         valid;                                  \
74                    uint8_t         writeflag;                              \
75                    addrtype        vaddr_page;                             \
76                    addrtype        paddr_page;                             \
77                    unsigned char   *host_page;                             \
78                    int64_t         timestamp;                              \
79            };
80    
81    #define DYNTRANS_MISC64_DECLARATIONS(arch,ARCH,tlbindextype)            \
82            struct arch ## _l3_64_table {                                   \
83                    unsigned char   *host_load[1 << ARCH ## _L3N];          \
84                    unsigned char   *host_store[1 << ARCH ## _L3N];         \
85                    uint64_t        phys_addr[1 << ARCH ## _L3N];           \
86                    tlbindextype    vaddr_to_tlbindex[1 << ARCH ## _L3N];   \
87                    struct arch ## _tc_physpage *phys_page[1 << ARCH ## _L3N]; \
88                    struct arch ## _l3_64_table     *next;                  \
89                    int             refcount;                               \
90            };                                                              \
91            struct arch ## _l2_64_table {                                   \
92                    struct arch ## _l3_64_table     *l3[1 << ARCH ## _L2N]; \
93                    struct arch ## _l2_64_table     *next;                  \
94                    int                             refcount;               \
95            };
96    
97    /*
98     *  Dyntrans "Instruction Translation Cache":
99     *
100     *  cur_physpage is a pointer to the current physpage. (It _HAPPENS_ to
101     *  be the same as cur_ic_page, because all the instrcalls should be placed
102     *  first in the physpage struct!)
103     *
104     *  cur_ic_page is a pointer to an array of xxx_IC_ENTRIES_PER_PAGE
105     *  instruction call entries.
106     *
107     *  next_ic points to the next such instruction call to be executed.
108     *
109     *  combination_check, when set to non-NULL, is executed automatically after
110     *  an instruction has been translated. (It check for combinations of
111     *  instructions; low_addr is the offset of the translated instruction in the
112     *  current page, NOT shifted right.)
113     */
114    #define DYNTRANS_ITC(arch)      struct arch ## _tc_physpage *cur_physpage;  \
115                                    struct arch ## _instr_call  *cur_ic_page;   \
116                                    struct arch ## _instr_call  *next_ic;       \
117                                    void (*combination_check)(struct cpu *,     \
118                                        struct arch ## _instr_call *, int low_addr);
119    
120    /*
121     *  Virtual -> physical -> host address translation TLB entries:
122     *  ------------------------------------------------------------
123     *
124     *  Regardless of whether 32-bit or 64-bit address translation is used, the
125     *  same TLB entry structure is used.
126     */
127    #define VPH_TLBS(arch,ARCH)                                             \
128            struct arch ## _vpg_tlb_entry                                   \
129                vph_tlb_entry[ARCH ## _MAX_VPH_TLB_ENTRIES];
130    
131    /*
132     *  32-bit dyntrans emulated Virtual -> physical -> host address translation:
133     *  -------------------------------------------------------------------------
134     *
135     *  This stuff assumes that 4 KB pages are used. 20 bits to select a page
136     *  means just 1 M entries needed. This is small enough that a couple of
137     *  full-size tables can fit in virtual memory on modern hosts (both 32-bit
138     *  and 64-bit hosts). :-)
139     *
140     *  Usage: e.g. VPH32(arm,ARM,uint32_t,uint8_t)
141     *           or VPH32(sparc,SPARC,uint64_t,uint16_t)
142     *
143     *  The vph_tlb_entry entries are cpu dependent tlb entries.
144     *
145     *  The host_load and host_store entries point to host pages; the phys_addr
146     *  entries are uint32_t or uint64_t (emulated physical addresses).
147     *
148     *  phys_page points to translation cache physpages.
149     *
150     *  phystranslation is a bitmap which tells us whether a physical page has
151     *  a code translation.
152     *
153     *  vaddr_to_tlbindex is a virtual address to tlb index hint table.
154     *  The values in this array are the tlb index plus 1, so a value of, say,
155     *  3 means tlb index 2. A value of 0 would mean a tlb index of -1, which
156     *  is not a valid index. (I.e. no hit.)
157     */
158    #define N_VPH32_ENTRIES         1048576
159    #define VPH32(arch,ARCH,paddrtype,tlbindextype)                         \
160            unsigned char           *host_load[N_VPH32_ENTRIES];            \
161            unsigned char           *host_store[N_VPH32_ENTRIES];           \
162            paddrtype               phys_addr[N_VPH32_ENTRIES];             \
163            struct arch ## _tc_physpage  *phys_page[N_VPH32_ENTRIES];       \
164            uint32_t                phystranslation[N_VPH32_ENTRIES/32];    \
165            tlbindextype            vaddr_to_tlbindex[N_VPH32_ENTRIES];
166    
167    /*
168     *  64-bit dyntrans emulated Virtual -> physical -> host address translation:
169     *  -------------------------------------------------------------------------
170     *
171     *  Usage: e.g. VPH64(alpha,ALPHA,uint8_t)
172     *           or VPH64(sparc,SPARC,uint16_t)
173     *
174     *  l1_64 is an array containing poiners to l2 tables.
175     *
176     *  l2_64_dummy is a pointer to a "dummy l2 table". Instead of having NULL
177     *  pointers in l1_64 for unused slots, a pointer to the dummy table can be
178     *  used.
179     */
180    #define DYNTRANS_L1N            17
181    #define VPH64(arch,ARCH,tlbindextype)                                   \
182            struct arch ## _l3_64_table     *l3_64_dummy;                   \
183            struct arch ## _l3_64_table     *next_free_l3;                  \
184            struct arch ## _l2_64_table     *l2_64_dummy;                   \
185            struct arch ## _l2_64_table     *next_free_l2;                  \
186            struct arch ## _l2_64_table     *l1_64[1 << DYNTRANS_L1N];
187    
188    
189    /*  Include all CPUs' header files here:  */
190  #include "cpu_alpha.h"  #include "cpu_alpha.h"
191  #include "cpu_arm.h"  #include "cpu_arm.h"
192  #include "cpu_avr.h"  #include "cpu_avr.h"
# Line 75  struct cpu_family { Line 221  struct cpu_family {
221                                      uint64_t *valuep, int *match_register);                                      uint64_t *valuep, int *match_register);
222          int                     (*disassemble_instr)(struct cpu *cpu,          int                     (*disassemble_instr)(struct cpu *cpu,
223                                      unsigned char *instr, int running,                                      unsigned char *instr, int running,
224                                      uint64_t dumpaddr, int bintrans);                                      uint64_t dumpaddr);
225          void                    (*register_dump)(struct cpu *cpu,          void                    (*register_dump)(struct cpu *cpu,
226                                      int gprs, int coprocs);                                      int gprs, int coprocs);
227          int                     (*run)(struct emul *emul,          int                     (*run)(struct emul *emul,
228                                      struct machine *machine);                                      struct machine *machine);
229          void                    (*dumpinfo)(struct cpu *cpu);          void                    (*dumpinfo)(struct cpu *cpu);
         void                    (*show_full_statistics)(struct machine *m);  
230          void                    (*tlbdump)(struct machine *m, int x,          void                    (*tlbdump)(struct machine *m, int x,
231                                      int rawflag);                                      int rawflag);
232          int                     (*interrupt)(struct cpu *cpu, uint64_t irq_nr);          int                     (*interrupt)(struct cpu *cpu, uint64_t irq_nr);
# Line 89  struct cpu_family { Line 234  struct cpu_family {
234                                      uint64_t irq_nr);                                      uint64_t irq_nr);
235          void                    (*functioncall_trace)(struct cpu *,          void                    (*functioncall_trace)(struct cpu *,
236                                      uint64_t f, int n_args);                                      uint64_t f, int n_args);
237            char                    *(*gdb_stub)(struct cpu *, char *cmd);
238  };  };
239    
 #ifdef TRACE_NULL_CRASHES  
 #define TRACE_NULL_N_ENTRIES            16  
 #endif  
   
240    
241  /*  /*
242   *  Dynamic translation definitions:   *  More dyntrans stuff:
243   *   *
244   *  The translation cache begins with N_BASE_TABLE_ENTRIES uint32_t offsets   *  The translation cache begins with N_BASE_TABLE_ENTRIES uint32_t offsets
245   *  into the cache, for possible translation cache structs for physical pages.   *  into the cache, for possible translation cache structs for physical pages.
# Line 107  struct cpu_family { Line 249  struct cpu_family {
249  #define TRANSLATIONS                    1  #define TRANSLATIONS                    1
250  #define COMBINATIONS                    2  #define COMBINATIONS                    2
251    
252    /*  Meaning of delay_slot:  */
253    #define NOT_DELAYED                     0
254    #define DELAYED                         1
255    #define TO_BE_DELAYED                   2
256    #define EXCEPTION_IN_DELAY_SLOT         0x100
257    
258    #define N_SAFE_DYNTRANS_LIMIT_SHIFT     14
259    #define N_SAFE_DYNTRANS_LIMIT   ((1 << (N_SAFE_DYNTRANS_LIMIT_SHIFT - 1)) - 1)
260    
261  #define DYNTRANS_CACHE_SIZE             (16*1048576)  #define DYNTRANS_CACHE_SIZE             (16*1048576)
262  #define DYNTRANS_CACHE_MARGIN           300000  #define DYNTRANS_CACHE_MARGIN           300000
263    
# Line 140  struct cpu { Line 291  struct cpu {
291          void            (*update_translation_table)(struct cpu *,          void            (*update_translation_table)(struct cpu *,
292                              uint64_t vaddr_page, unsigned char *host_page,                              uint64_t vaddr_page, unsigned char *host_page,
293                              int writeflag, uint64_t paddr_page);                              int writeflag, uint64_t paddr_page);
294          void            (*invalidate_translation_caches_paddr)(struct cpu *,          void            (*invalidate_translation_caches)(struct cpu *,
295                              uint64_t paddr, int flags);                              uint64_t paddr, int flags);
296          void            (*invalidate_code_translation)(struct cpu *,          void            (*invalidate_code_translation)(struct cpu *,
297                              uint64_t paddr, int flags);                              uint64_t paddr, int flags);
298          void            (*useremul_syscall)(struct cpu *cpu, uint32_t code);          void            (*useremul_syscall)(struct cpu *cpu, uint32_t code);
299            int             (*instruction_has_delayslot)(struct cpu *cpu,
300                                unsigned char *ib);
301    
302          uint64_t        pc;          uint64_t        pc;
303    
 #ifdef TRACE_NULL_CRASHES  
         /*  TODO: remove this, it's MIPS only  */  
         int             trace_null_index;  
         uint64_t        trace_null_addr[TRACE_NULL_N_ENTRIES];  
 #endif    
   
304          int             trace_tree_depth;          int             trace_tree_depth;
305    
306          /*          /*
# Line 164  struct cpu { Line 311  struct cpu {
311          unsigned char   *translation_cache;          unsigned char   *translation_cache;
312          size_t          translation_cache_cur_ofs;          size_t          translation_cache_cur_ofs;
313    
314            uint64_t        delay_jmpaddr;  /*  only used if delay_slot > 0  */
315            int             delay_slot;
316    
317          /*          /*
318           *  CPU-family dependent:           *  CPU-family dependent:
319           */           */
# Line 187  struct cpu { Line 337  struct cpu {
337  /*  cpu.c:  */  /*  cpu.c:  */
338  struct cpu *cpu_new(struct memory *mem, struct machine *machine,  struct cpu *cpu_new(struct memory *mem, struct machine *machine,
339          int cpu_id, char *cpu_type_name);          int cpu_id, char *cpu_type_name);
 void cpu_show_full_statistics(struct machine *m);  
340  void cpu_tlbdump(struct machine *m, int x, int rawflag);  void cpu_tlbdump(struct machine *m, int x, int rawflag);
341  void cpu_register_match(struct machine *m, char *name,  void cpu_register_match(struct machine *m, char *name,
342          int writeflag, uint64_t *valuep, int *match_register);          int writeflag, uint64_t *valuep, int *match_register);
343  void cpu_register_dump(struct machine *m, struct cpu *cpu,  void cpu_register_dump(struct machine *m, struct cpu *cpu,
344          int gprs, int coprocs);          int gprs, int coprocs);
345  int cpu_disassemble_instr(struct machine *m, struct cpu *cpu,  int cpu_disassemble_instr(struct machine *m, struct cpu *cpu,
346          unsigned char *instr, int running, uint64_t addr, int bintrans);          unsigned char *instr, int running, uint64_t addr);
347    char *cpu_gdb_stub(struct cpu *cpu, char *cmd);
348  int cpu_interrupt(struct cpu *cpu, uint64_t irq_nr);  int cpu_interrupt(struct cpu *cpu, uint64_t irq_nr);
349  int cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr);  int cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr);
350  void cpu_functioncall_trace(struct cpu *cpu, uint64_t f);  void cpu_functioncall_trace(struct cpu *cpu, uint64_t f);
# Line 214  void cpu_init(void); Line 364  void cpu_init(void);
364  #define INVALIDATE_ALL                  2  #define INVALIDATE_ALL                  2
365  #define INVALIDATE_PADDR                4  #define INVALIDATE_PADDR                4
366  #define INVALIDATE_VADDR                8  #define INVALIDATE_VADDR                8
367    #define INVALIDATE_VADDR_UPPER4         16      /*  useful for PPC emulation  */
368    
369    #define TLB_CODE                        0x02
370    
371    
372  #define CPU_FAMILY_INIT(n,s)    int n ## _cpu_family_init(              \  #define CPU_FAMILY_INIT(n,s)    int n ## _cpu_family_init(              \
# Line 227  void cpu_init(void); Line 380  void cpu_init(void);
380          fp->register_dump = n ## _cpu_register_dump;                    \          fp->register_dump = n ## _cpu_register_dump;                    \
381          fp->run = n ## _cpu_run;                                        \          fp->run = n ## _cpu_run;                                        \
382          fp->dumpinfo = n ## _cpu_dumpinfo;                              \          fp->dumpinfo = n ## _cpu_dumpinfo;                              \
         fp->show_full_statistics = n ## _cpu_show_full_statistics;      \  
         fp->tlbdump = n ## _cpu_tlbdump;                                \  
383          fp->interrupt = n ## _cpu_interrupt;                            \          fp->interrupt = n ## _cpu_interrupt;                            \
384          fp->interrupt_ack = n ## _cpu_interrupt_ack;                    \          fp->interrupt_ack = n ## _cpu_interrupt_ack;                    \
385          fp->functioncall_trace = n ## _cpu_functioncall_trace;          \          fp->functioncall_trace = n ## _cpu_functioncall_trace;          \
386            fp->gdb_stub = n ## _cpu_gdb_stub;                              \
387            fp->tlbdump = n ## _cpu_tlbdump;                                \
388          return 1;                                                       \          return 1;                                                       \
389          }          }
390    

Legend:
Removed from v.14  
changed lines
  Added in v.24

  ViewVC Help
Powered by ViewVC 1.1.26