Commit | Line | Data |
---|---|---|
2934d1c9 MH |
1 | #include "sysdep.h" |
2 | #include "bfd.h" | |
3 | #include "remote-sim.h" | |
4 | #include "callback.h" | |
5 | ||
6 | #include "d10v_sim.h" | |
7 | ||
8 | #define IMEM_SIZE 18 /* D10V instruction memory size is 18 bits */ | |
9 | #define DMEM_SIZE 16 /* Data memory */ | |
10 | ||
11 | uint16 OP[4]; | |
12 | ||
13 | static struct hash_entry *lookup_hash PARAMS ((uint32 ins, int size)); | |
14 | ||
15 | #define MAX_HASH 63 | |
16 | struct hash_entry | |
17 | { | |
18 | struct hash_entry *next; | |
19 | long opcode; | |
20 | long mask; | |
21 | struct simops *ops; | |
22 | }; | |
23 | ||
24 | struct hash_entry hash_table[MAX_HASH+1]; | |
25 | ||
26 | static long | |
27 | hash(insn, format) | |
28 | long insn; | |
29 | int format; | |
30 | { | |
31 | if (format & LONG_OPCODE) | |
32 | return ((insn & 0x3F000000) >> 24); | |
33 | else | |
34 | return((insn & 0x7E00) >> 9); | |
35 | } | |
36 | ||
37 | static struct hash_entry * | |
38 | lookup_hash (ins, size) | |
39 | uint32 ins; | |
40 | int size; | |
41 | { | |
42 | struct hash_entry *h; | |
43 | ||
44 | if (size) | |
45 | h = &hash_table[(ins & 0x3F000000) >> 24]; | |
46 | else | |
47 | h = &hash_table[(ins & 0x7E00) >> 9]; | |
48 | ||
49 | while ( (ins & h->mask) != h->opcode) | |
50 | { | |
51 | if (h->next == NULL) | |
52 | { | |
53 | printf ("ERROR looking up hash for %x\n",ins); | |
54 | exit(1); | |
55 | } | |
56 | h = h->next; | |
57 | } | |
58 | return (h); | |
59 | } | |
60 | ||
61 | uint32 | |
62 | get_longword_swap (x) | |
63 | uint16 x; | |
64 | { | |
65 | uint8 *a = (uint8 *)(x + State.imem); | |
66 | return (a[0]<<24) + (a[1]<<16) + (a[2]<<8) + (a[3]); | |
67 | } | |
68 | ||
69 | uint16 | |
70 | get_word_swap (x) | |
71 | uint16 x; | |
72 | { | |
73 | uint8 *a = (uint8 *)(x + State.imem); | |
74 | return (a[0]<<8) + a[1]; | |
75 | } | |
76 | ||
77 | void | |
78 | write_word_swap (addr, data) | |
79 | uint16 addr, data; | |
80 | { | |
81 | uint8 *a = (uint8 *)(addr + State.imem); | |
82 | a[0] = data >> 8; | |
83 | a[1] = data & 0xff; | |
84 | } | |
85 | ||
86 | ||
87 | static void | |
88 | get_operands (struct simops *s, uint32 ins) | |
89 | { | |
90 | int i, shift, bits, flags; | |
91 | uint32 mask; | |
92 | for (i=0; i < s->numops; i++) | |
93 | { | |
94 | shift = s->operands[3*i]; | |
95 | bits = s->operands[3*i+1]; | |
96 | flags = s->operands[3*i+2]; | |
97 | mask = 0x7FFFFFFF >> (31 - bits); | |
98 | OP[i] = (ins >> shift) & mask; | |
99 | } | |
100 | } | |
101 | ||
102 | static void | |
103 | do_long (ins) | |
104 | uint32 ins; | |
105 | { | |
106 | struct hash_entry *h; | |
107 | /* printf ("do_long %x\n",ins); */ | |
108 | h = lookup_hash (ins, 1); | |
109 | get_operands (h->ops, ins); | |
110 | (h->ops->func)(); | |
111 | } | |
112 | static void | |
113 | do_2_short (ins1, ins2) | |
114 | uint16 ins1, ins2; | |
115 | { | |
116 | struct hash_entry *h; | |
117 | /* printf ("do_2_short %x -> %x\n",ins1,ins2); */ | |
118 | h = lookup_hash (ins1, 0); | |
119 | get_operands (h->ops, ins1); | |
120 | (h->ops->func)(); | |
121 | h = lookup_hash (ins2, 0); | |
122 | get_operands (h->ops, ins2); | |
123 | (h->ops->func)(); | |
124 | } | |
125 | static void | |
126 | do_parallel (ins1, ins2) | |
127 | uint16 ins1, ins2; | |
128 | { | |
129 | struct hash_entry *h1, *h2; | |
130 | /* printf ("do_parallel %x || %x\n",ins1,ins2); */ | |
131 | h1 = lookup_hash (ins1, 0); | |
132 | get_operands (h1->ops, ins1); | |
133 | h2 = lookup_hash (ins2, 0); | |
134 | get_operands (h2->ops, ins2); | |
135 | if (h1->ops->exec_type == PARONLY) | |
136 | { | |
137 | (h1->ops->func)(); | |
138 | if (State.exe) | |
139 | (h2->ops->func)(); | |
140 | } | |
141 | else if (h2->ops->exec_type == PARONLY) | |
142 | { | |
143 | (h2->ops->func)(); | |
144 | if (State.exe) | |
145 | (h1->ops->func)(); | |
146 | } | |
147 | else | |
148 | { | |
149 | (h1->ops->func)(); | |
150 | (h2->ops->func)(); | |
151 | } | |
152 | } | |
153 | ||
154 | ||
155 | void | |
156 | sim_size (power) | |
157 | int power; | |
158 | ||
159 | { | |
160 | if (State.imem) | |
161 | { | |
162 | free (State.imem); | |
163 | free (State.dmem); | |
164 | } | |
165 | ||
166 | State.imem = (uint8 *)calloc(1,1<<IMEM_SIZE); | |
167 | State.dmem = (uint8 *)calloc(1,1<<DMEM_SIZE); | |
168 | if (!State.imem || !State.dmem ) | |
169 | { | |
170 | fprintf (stderr,"Memory allocation failed.\n"); | |
171 | exit(1); | |
172 | } | |
173 | printf ("Allocated %d bytes instruction memory and\n",1<<IMEM_SIZE); | |
174 | printf (" %d bytes data memory.\n",1<<DMEM_SIZE); | |
175 | } | |
176 | ||
177 | static void | |
178 | init_system () | |
179 | { | |
180 | if (!State.imem) | |
181 | sim_size(1); | |
182 | } | |
183 | ||
184 | int | |
185 | sim_write (addr, buffer, size) | |
186 | SIM_ADDR addr; | |
187 | unsigned char *buffer; | |
188 | int size; | |
189 | { | |
190 | int i; | |
191 | init_system (); | |
192 | ||
193 | printf ("sim_write %d bytes to 0x%x\n",size,addr); | |
194 | for (i = 0; i < size; i++) | |
195 | { | |
196 | State.imem[i+addr] = buffer[i]; | |
197 | } | |
198 | return size; | |
199 | } | |
200 | ||
201 | void | |
202 | sim_open (args) | |
203 | char *args; | |
204 | { | |
205 | struct simops *s; | |
206 | struct hash_entry *h, *prev; | |
207 | if (args != NULL) | |
208 | printf ("sim_open %s\n",args); | |
209 | ||
210 | /* put all the opcodes in the hash table */ | |
211 | for (s = Simops; s->func; s++) | |
212 | { | |
213 | h = &hash_table[hash(s->opcode,s->format)]; | |
214 | ||
215 | /* go to the last entry in the chain */ | |
216 | while (h->next) | |
217 | h = h->next; | |
218 | ||
219 | if (h->ops) | |
220 | { | |
221 | h->next = calloc(1,sizeof(struct hash_entry)); | |
222 | h = h->next; | |
223 | } | |
224 | h->ops = s; | |
225 | h->mask = s->mask; | |
226 | h->opcode = s->opcode; | |
227 | } | |
228 | } | |
229 | ||
230 | ||
231 | void | |
232 | sim_close (quitting) | |
233 | int quitting; | |
234 | { | |
235 | /* nothing to do */ | |
236 | } | |
237 | ||
238 | void | |
239 | sim_set_profile (n) | |
240 | int n; | |
241 | { | |
242 | printf ("sim_set_profile %d\n",n); | |
243 | } | |
244 | ||
245 | void | |
246 | sim_set_profile_size (n) | |
247 | int n; | |
248 | { | |
249 | printf ("sim_set_profile_size %d\n",n); | |
250 | } | |
251 | ||
252 | void | |
253 | sim_resume (step, siggnal) | |
254 | int step, siggnal; | |
255 | { | |
256 | uint32 inst; | |
257 | int i; | |
258 | reg_t oldpc; | |
259 | ||
260 | printf ("sim_resume %d %d\n",step,siggnal); | |
261 | ||
262 | while (1) | |
263 | { | |
264 | inst = RLW (PC << 2); | |
265 | oldpc = PC; | |
266 | switch (inst & 0xC0000000) | |
267 | { | |
268 | case 0xC0000000: | |
269 | /* long instruction */ | |
270 | do_long (inst & 0x3FFFFFFF); | |
271 | break; | |
272 | case 0x80000000: | |
273 | /* R -> L */ | |
274 | do_2_short ( inst & 0x7FFF, (inst & 0x3FFF8000) >> 15); | |
275 | break; | |
276 | case 0x40000000: | |
277 | /* L -> R */ | |
278 | do_2_short ((inst & 0x3FFF8000) >> 15, inst & 0x7FFF); | |
279 | break; | |
280 | case 0: | |
281 | do_parallel ((inst & 0x3FFF8000) >> 15, inst & 0x7FFF); | |
282 | break; | |
283 | } | |
284 | ||
285 | if (State.RP && PC == RPT_E) | |
286 | { | |
287 | RPT_C -= 1; | |
288 | if (RPT_C == 0) | |
289 | State.RP = 0; | |
290 | else | |
291 | PC = RPT_S; | |
292 | } | |
293 | ||
294 | /* FIXME */ | |
295 | if (PC == oldpc) | |
296 | PC++; | |
297 | } | |
298 | } | |
299 | ||
300 | int | |
301 | sim_trace () | |
302 | { | |
303 | printf ("sim_trace\n"); | |
304 | return 0; | |
305 | } | |
306 | ||
307 | void | |
308 | sim_info (verbose) | |
309 | int verbose; | |
310 | { | |
311 | printf ("sim_verbose\n"); | |
312 | } | |
313 | ||
314 | void | |
315 | sim_create_inferior (start_address, argv, env) | |
316 | SIM_ADDR start_address; | |
317 | char **argv; | |
318 | char **env; | |
319 | { | |
320 | printf ("sim_create_inferior: PC=0x%x\n",start_address); | |
321 | PC = start_address >> 2; | |
322 | } | |
323 | ||
324 | ||
325 | void | |
326 | sim_kill () | |
327 | { | |
328 | /* nothing to do */ | |
329 | } | |
330 | ||
331 | void | |
332 | sim_set_callbacks(p) | |
333 | host_callback *p; | |
334 | { | |
335 | printf ("sim_set_callbacks\n"); | |
336 | /* callback = p; */ | |
337 | } | |
338 | ||
339 | void | |
340 | sim_stop_reason (reason, sigrc) | |
341 | enum sim_stop *reason; | |
342 | int *sigrc; | |
343 | { | |
344 | printf ("sim_stop_reason\n"); | |
345 | } |