1 /* collection of junk waiting time to sort out
2 Copyright (C) 1999 Cygnus Solutions. */
7 /* GDB register numbers, will eventually live in more public place. */
8 #define SPARC32_PC_REGNUM 68
9 #define SPARC32_NPC_REGNUM 69
10 #define SPARC64_PC_REGNUM ?
11 #define SPARC64_NPC_REGNUM ?
13 /* Commonly used registers. */
23 #define CURRENT_GREGS(cpu) (& (cpu)->current_regs[0])
24 #define CURRENT_OREGS(cpu) (& (cpu)->current_regs[8])
25 #define CURRENT_LREGS(cpu) (& (cpu)->current_regs[16])
26 #define CURRENT_IREGS(cpu) (& (cpu)->current_regs[24])
28 /* The register windows are recorded in a seemingly backwards manner.
29 %i0-7 live at lower addresses in memory than %o0-7 (even though they
30 have higher register numbers). This is because on v9 the stack grows
31 upwards in the sense that CWP increases during a "push" (save) operation.
32 On v8 CWP decreases during a "push" (save) operation. */
34 #define REAL_GREGS(cpu) \
35 (& (cpu)->global_regs[0])
36 #define REAL_IREGS(cpu, win) \
37 (& (cpu)->win_regs[win][0])
38 #define REAL_LREGS(cpu, win) \
39 (& (cpu)->win_regs[win][8])
40 #ifdef WANT_CPU_SPARC32
41 #define REAL_OREGS(cpu, win) \
42 (& (cpu)->win_regs[ROUND_WIN ((win) - 1)][0])
44 #ifdef WANT_CPU_SPARC64
45 #define REAL_OREGS(cpu, win) \
46 (& (cpu)->win_regs[ROUND_WIN ((win) + 1)][0])
51 /* Various ways to handle register windows:
52 - don't, do all index calculations at runtime
53 - table of lookup tables, one entry for each window
54 - working copy of registers that is swapped in/out on each
55 register window change
56 - table of 32 pointers, one for each regs
57 - table of 4 pointers, one for each of g,o,l,i regs
61 /* FIXME: Hardcodes number of windows. */
62 #define GET_NWINDOWS() NWINDOWS
64 /* We take advantage of the fact that NWINDOWS is always a power of two. */
65 #define ROUND_WIN(x) ((x) & (NWINDOWS - 1))
67 /* Return the next and previous windows of WIN.
68 Note that the next window for sparc32 is win-1 whereas the next window
69 for sparc64 is win+1. */
70 #ifdef WANT_CPU_SPARC32
71 #define NEXT_WIN(win) ROUND_WIN ((win) - 1)
72 #define PREV_WIN(win) ROUND_WIN ((win) + 1)
74 #ifdef WANT_CPU_SPARC64
75 #define NEXT_WIN(win) ROUND_WIN ((win) + 1)
76 #define PREV_WIN(win) ROUND_WIN ((win) - 1)
79 #if 0 /* FIXME: Use GET_H_FOO */
80 /* These are v9 specific. */
81 #define GET_CANSAVE(cpu_) (cpu_->cgen_cpu.cpu.h_cansave)
82 #define GET_CANRESTORE(cpu_) (cpu_->cgen_cpu.cpu.h_canrestore)
83 #define GET_CLEANWIN(cpu_) (cpu_->cgen_cpu.cpu.h_cleanwin)
84 #define GET_OTHERWIN(cpu_) (cpu_->cgen_cpu.cpu.h_otherwin)
85 #define GET_WSTATE(cpu_) (cpu_->cgen_cpu.cpu.h_wstate)
87 /* These are v9 specific. */
88 #define SET_CANSAVE(cpu_, x) (cpu_->cgen_cpu.cpu.h_cansave = (x))
89 #define SET_CANRESTORE(cpu_, x) (cpu_->cgen_cpu.cpu.h_canrestore = (x))
90 #define SET_CLEANWIN(cpu_, x) (cpu_->cgen_cpu.cpu.h_cleanwin = (x))
91 #define SET_OTHERWIN(cpu_, x) (cpu_->cgen_cpu.cpu.h_otherwin = (x))
92 #define SET_WSTATE(cpu_, x) (cpu_->cgen_cpu.cpu.h_wstate = (x))
95 #define CPU32_CGEN(cpu) (& (cpu)->sparc_cpu.sparc32.cpu_cgen)
97 #ifdef WANT_CPU_SPARC32
98 /*#define ARGBUF SPARC32_ARGBUF*/
99 #define CPU_PROFILE_STATE(cpu) (& CPU32 (cpu)->cpu_profile)
100 /* Macro to access heart of cpu: the registers, etc. */
101 #define CPU_CGEN(cpu) CPU32_CGEN (cpu)
104 #define CPU64_CGEN(cpu) (& (cpu)->sparc_cpu.sparc64.cpu_cgen)
106 #ifdef WANT_CPU_SPARC64
107 /*#define ARGBUF SPARC64_ARGBUF*/
108 #define CPU_PROFILE_STATE(cpu) (& CPU64 (cpu)->cpu_profile)
109 /* Macro to access heart of cpu: the registers, etc. */
110 #define CPU_CGEN(cpu) CPU64_CGEN (cpu)
115 #define DECLARE_GETMEM(mode, size) \
116 extern mode XCONCAT3 (GETMEM,mode,ASI) (SIM_CPU *, IADDR, ADDR, INT);
118 DECLARE_GETMEM (QI
, 1)
119 DECLARE_GETMEM (UQI
, 1)
120 DECLARE_GETMEM (HI
, 2)
121 DECLARE_GETMEM (UHI
, 2)
122 DECLARE_GETMEM (SI
, 4)
123 DECLARE_GETMEM (USI
, 4)
124 DECLARE_GETMEM (DI
, 8)
125 DECLARE_GETMEM (UDI
, 8)
127 #undef DECLARE_GETMEM
129 #define DECLARE_SETMEM(mode, size) \
130 extern void XCONCAT3 (SETMEM,mode,ASI) (SIM_CPU *, IADDR, ADDR, INT, mode);
132 DECLARE_SETMEM (QI
, 1)
133 DECLARE_SETMEM (UQI
, 1)
134 DECLARE_SETMEM (HI
, 2)
135 DECLARE_SETMEM (UHI
, 2)
136 DECLARE_SETMEM (SI
, 4)
137 DECLARE_SETMEM (USI
, 4)
138 DECLARE_SETMEM (DI
, 8)
139 DECLARE_SETMEM (UDI
, 8)
141 #undef DECLARE_SETMEM
143 /* Misc. support routines. */
145 void sparc32_cold_reset (SIM_CPU
*, int userland_p_
);
147 SI
sparc32_do_restore (SIM_CPU
*, IADDR pc_
, SI rs1_
, SI rs2_simm13_
);
148 SI
sparc32_do_save (SIM_CPU
*, IADDR pc_
, SI rs1_
, SI rs2_simm13_
);
150 void sparc32_do_ldstub (SIM_CPU
*, IADDR pc_
, INT rd_regno_
,
151 SI rs1_
, SI rs2_simm13_
, INT asi_
);
152 void sparc32_do_swap (SIM_CPU
*, IADDR pc_
, INT rd_regno_
,
153 SI rs1_
, SI rs2_simm13_
, INT asi_
);
155 void sparc32_invalid_insn (SIM_CPU
*, IADDR pc_
);
156 void sparc32_core_signal (SIM_DESC
, SIM_CPU
*, sim_cia pc_
,
157 unsigned int map_
, int nr_bytes_
, address_word addr_
,
158 transfer_type transfer_
, sim_core_signals sig_
);
160 /* Profiling support. */
162 void model_mark_get_h_gr (SIM_CPU
*, void *);
163 void model_mark_set_h_gr (SIM_CPU
*, void *);
164 void model_mark_busy_reg (SIM_CPU
*, void *);
165 void model_mark_unbusy_reg (SIM_CPU
*, void *);
167 /* Called by semantic code to annul the next insn. */
169 #define SEM_ANNUL_INSN(cpu, pc, yes) \
170 do { CPU_CGEN_HW (cpu)->h_annul_p = (yes); } while (0)
172 #if 0 /* old experiment */
174 /* Macros used by the semantic code generator and cgen-run.c to control
177 /* Value returned for the next PC when a branch has occured. */
178 #define PC_BRANCH_INSN 3
180 /* Value of npc when there is no delay slot. */
181 #define NPC_NO_DELAY_INSN 3
183 /* CURRENT_CPU isn't used, a variable of same name must exist for SET_H_NPC */
184 #define BRANCH_NEW_PC(current_cpu, var, addr) \
188 var = PC_BRANCH_INSN; \
191 /* Mark the next instruction as being annulled if YES is non-zero.
192 VAR is the local variable that contains the next PC value.
193 CURRENT_CPU isn't used, a variable of same name must exist for SET_H_NPC */
194 #define ANNUL_NEXT_INSN(current_cpu, var, yes) \
198 SET_H_ANNUL_P (yes); \
199 var = PC_BRANCH_INSN; \
204 We also have to watch for delay slots and annulled insns.
205 current_cpu isn't used, a variable of same name must exist for SET_H_PC */
206 #define UPDATE_PC(current_cpu, new_pc) \
208 if ((new_pc) == PC_BRANCH_INSN) \
210 int annul_p = GET_H_ANNUL_P (); \
211 PCADDR npc = GET_H_NPC (); \
213 if (npc != NPC_NO_DELAY_INSN) \
217 /* FIXME: Could update cycle count. */ \
219 SET_H_NPC (NPC_NO_DELAY_INSN) ; \
222 goto GotoFirstInsn; \
226 /* Untaken annulled branch. */ \
227 /* FIXME: Could update cycle count. */ \
229 SET_H_PC (GET_H_PC () + 8); \
236 /* Return nonzero if in non-annulled delay slot. */
237 #define EXECUTE_FIRST_INSN_P(current_cpu) \
238 (GET_H_NPC () != NPC_NO_DELAY_INSN)
240 /* Called when the first instruction is in non-annulled delay slot. */
242 #define EXECUTE_FIRST_INSN(current_cpu, sc, fast_p) \
244 PCADDR new_pc = execute (current_cpu, sc, fast_p); \
245 if (new_pc == PC_BRANCH_INSN) \
247 abort (); /* FIXME: dcti in delay slot not handled yet */ \
251 SET_H_PC (GET_H_NPC ()); \
252 SET_H_NPC (NPC_NO_DELAY_INSN); \
256 #endif /* old experiment */
258 #endif /* SPARC_SIM_H */
This page took 0.038221 seconds and 4 git commands to generate.