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

Contents of /upstream/0.3.2/src/cpu_hppa.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5 - (show annotations)
Mon Oct 8 16:18:06 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 8271 byte(s)
0.3.2
1 /*
2 * Copyright (C) 2005 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_hppa.c,v 1.4 2005/04/15 21:39:59 debug Exp $
29 *
30 * HPPA CPU emulation.
31 *
32 * TODO: This is just a dummy so far.
33 */
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <ctype.h>
39
40 #include "misc.h"
41
42
43 #ifndef ENABLE_HPPA
44
45
46 #include "cpu_hppa.h"
47
48
49 /*
50 * hppa_cpu_family_init():
51 *
52 * Bogus, when ENABLE_HPPA isn't defined.
53 */
54 int hppa_cpu_family_init(struct cpu_family *fp)
55 {
56 return 0;
57 }
58
59
60 #else /* ENABLE_HPPA */
61
62
63 #include "cpu.h"
64 #include "cpu_hppa.h"
65 #include "machine.h"
66 #include "memory.h"
67 #include "opcodes_hppa.h"
68 #include "symbol.h"
69
70
71 extern volatile int single_step;
72 extern int old_show_trace_tree;
73 extern int old_instruction_trace;
74 extern int old_quiet_mode;
75 extern int quiet_mode;
76
77
78 /*
79 * hppa_cpu_new():
80 *
81 * Create a new HPPA cpu object.
82 */
83 struct cpu *hppa_cpu_new(struct memory *mem, struct machine *machine,
84 int cpu_id, char *cpu_type_name)
85 {
86 struct cpu *cpu;
87
88 if (cpu_type_name == NULL)
89 return NULL;
90
91 if (strcasecmp(cpu_type_name, "HPPA1.0") != 0 &&
92 strcasecmp(cpu_type_name, "HPPA1.1") != 0 &&
93 strcasecmp(cpu_type_name, "HPPA2.0") != 0)
94 return NULL;
95
96 cpu = malloc(sizeof(struct cpu));
97 if (cpu == NULL) {
98 fprintf(stderr, "out of memory\n");
99 exit(1);
100 }
101
102 memset(cpu, 0, sizeof(struct cpu));
103 cpu->memory_rw = hppa_memory_rw;
104 cpu->name = cpu_type_name;
105 cpu->mem = mem;
106 cpu->machine = machine;
107 cpu->cpu_id = cpu_id;
108 cpu->byte_order = EMUL_BIG_ENDIAN;
109 cpu->bootstrap_cpu_flag = 0;
110 cpu->running = 0;
111
112 cpu->cd.hppa.bits = 32;
113 if (strcasecmp(cpu_type_name, "HPPA2.0") == 0)
114 cpu->cd.hppa.bits = 64;
115
116 /* Only show name and caches etc for CPU nr 0 (in SMP machines): */
117 if (cpu_id == 0) {
118 debug("%s", cpu->name);
119 }
120
121 return cpu;
122 }
123
124
125 /*
126 * hppa_cpu_dumpinfo():
127 */
128 void hppa_cpu_dumpinfo(struct cpu *cpu)
129 {
130 debug(" (%i-bit)", cpu->cd.hppa.bits);
131
132 debug("\n");
133 }
134
135
136 /*
137 * hppa_cpu_list_available_types():
138 *
139 * Print a list of available HPPA CPU types.
140 */
141 void hppa_cpu_list_available_types(void)
142 {
143 debug("HPPA1.0 HPPA1.1 HPPA2.0\n");
144 }
145
146
147 /*
148 * hppa_cpu_register_match():
149 */
150 void hppa_cpu_register_match(struct machine *m, char *name,
151 int writeflag, uint64_t *valuep, int *match_register)
152 {
153 int cpunr = 0;
154
155 /* CPU number: */
156
157 /* TODO */
158
159 /* Register name: */
160 if (strcasecmp(name, "pc") == 0) {
161 if (writeflag) {
162 m->cpus[cpunr]->pc = *valuep;
163 } else
164 *valuep = m->cpus[cpunr]->pc;
165 *match_register = 1;
166 }
167
168 /* TODO: _LOTS_ of stuff. */
169 }
170
171
172 /*
173 * hppa_cpu_disassemble_instr():
174 *
175 * Convert an instruction word into human readable format, for instruction
176 * tracing.
177 *
178 * If running is 1, cpu->pc should be the address of the instruction.
179 *
180 * If running is 0, things that depend on the runtime environment (eg.
181 * register contents) will not be shown, and addr will be used instead of
182 * cpu->pc for relative addresses.
183 */
184 int hppa_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr,
185 int running, uint64_t dumpaddr, int bintrans)
186 {
187 uint64_t offset;
188 uint32_t iword;
189 char *symbol;
190 int hi6, imm, rr, rb;
191
192 if (running)
193 dumpaddr = cpu->pc;
194
195 symbol = get_symbol_name(&cpu->machine->symbol_context,
196 dumpaddr, &offset);
197 if (symbol != NULL && offset==0)
198 debug("<%s>\n", symbol);
199
200 if (cpu->machine->ncpus > 1 && running)
201 debug("cpu%i: ", cpu->cpu_id);
202
203 if (cpu->cd.hppa.bits == 32)
204 debug("%08x", (int)dumpaddr);
205 else
206 debug("%016llx", (long long)dumpaddr);
207
208 /* NOTE: Fixed to big-endian. */
209 iword = (instr[0] << 24) + (instr[1] << 16) + (instr[2] << 8)
210 + instr[3];
211
212 debug(": %08x\t", iword);
213
214 if (bintrans && !running) {
215 debug("(bintrans)");
216 goto disasm_ret;
217 }
218
219 /*
220 * Decode the instruction:
221 */
222
223 hi6 = iword >> 26;
224
225 switch (hi6) {
226 case HPPA_LDIL:
227 rr = (iword >> 21) & 31;
228 imm = assemble_21(iword & 0x1fffff);
229 imm <<= 11;
230 debug("ldil\t0x%x,r%i", imm, rr);
231 break;
232 case HPPA_STW:
233 case HPPA_STW_1B:
234 rb = (iword >> 21) & 31;
235 rr = (iword >> 16) & 31;
236
237 /* TODO: hahahahaha, assemble_16 is really weird */
238
239 imm = (int16_t)(iword & 0xffff);
240 debug("stw\tr%i,%i(r%i)", rr, imm, rb);
241 break;
242 default:
243 debug("unimplemented hi6=%i", hi6);
244 }
245
246 disasm_ret:
247 debug("\n");
248 return sizeof(iword);
249 }
250
251
252 /*
253 * hppa_cpu_run_instr():
254 *
255 * Execute one instruction on a specific CPU.
256 *
257 * Return value is the number of instructions executed during this call,
258 * 0 if no instruction was executed.
259 */
260 int hppa_cpu_run_instr(struct emul *emul, struct cpu *cpu)
261 {
262 uint32_t iword;
263 unsigned char buf[4];
264 uint64_t cached_pc;
265 int r, i, hi6, rt, imm;
266
267 cached_pc = cpu->pc;
268
269 /* Check PC against breakpoints: */
270 if (!single_step)
271 for (i=0; i<cpu->machine->n_breakpoints; i++)
272 if (cached_pc == cpu->machine->breakpoint_addr[i]) {
273 fatal("Breakpoint reached, pc=0x");
274 if (cpu->cd.hppa.bits == 32)
275 fatal("%08x", (int)cached_pc);
276 else
277 fatal("%016llx", (long long)cached_pc);
278 fatal("\n");
279 single_step = 1;
280 return 0;
281 }
282
283 r = cpu->memory_rw(cpu, cpu->mem, cached_pc, &buf[0], sizeof(buf),
284 MEM_READ, CACHE_INSTRUCTION | PHYSICAL);
285 if (!r)
286 return 0;
287
288 iword = (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3];
289
290 if (cpu->machine->instruction_trace)
291 hppa_cpu_disassemble_instr(cpu, buf, 1, 0, 0);
292
293 cpu->cd.hppa.pc_last = cpu->pc;
294 cpu->pc += sizeof(iword);
295
296 hi6 = iword >> 26;
297
298 switch (hi6) {
299 case HPPA_LDIL:
300 rt = (iword >> 21) & 31;
301 imm = assemble_21(iword & 0x1fffff) << 1;
302 cpu->cd.hppa.gr[rt] = (int64_t)(int32_t) imm;
303 break;
304 default:
305 fatal("[ unimplemented HPPA hi6 = 0x%02x, pc = 0x%016llx ]\n",
306 hi6, (long long) (cpu->cd.hppa.pc_last));
307 cpu->running = 0;
308 return 0;
309 }
310
311 return 1;
312 }
313
314
315 #define MEMORY_RW hppa_memory_rw
316 #define MEM_HPPA
317 #include "memory_rw.c"
318 #undef MEM_HPPA
319 #undef MEMORY_RW
320
321
322 #define CPU_RUN hppa_cpu_run
323 #define CPU_RINSTR hppa_cpu_run_instr
324 #define CPU_RUN_HPPA
325 #include "cpu_run.c"
326 #undef CCPU_RINSTR
327 #undef CPU_RUN_HPPA
328 #undef CPU_RUN
329
330
331 /*
332 * hppa_cpu_family_init():
333 *
334 * Fill in the cpu_family struct for HPPA.
335 */
336 int hppa_cpu_family_init(struct cpu_family *fp)
337 {
338 fp->name = "HPPA";
339 fp->cpu_new = hppa_cpu_new;
340 fp->list_available_types = hppa_cpu_list_available_types;
341 fp->register_match = hppa_cpu_register_match;
342 fp->disassemble_instr = hppa_cpu_disassemble_instr;
343 /* fp->register_dump = hppa_cpu_register_dump; */
344 fp->run = hppa_cpu_run;
345 fp->dumpinfo = hppa_cpu_dumpinfo;
346 /* fp->show_full_statistics = hppa_cpu_show_full_statistics; */
347 /* fp->tlbdump = hppa_cpu_tlbdump; */
348 /* fp->interrupt = hppa_cpu_interrupt; */
349 /* fp->interrupt_ack = hppa_cpu_interrupt_ack; */
350 return 1;
351 }
352
353 #endif /* ENABLE_HPPA */

  ViewVC Help
Powered by ViewVC 1.1.26