/[gxemul]/trunk/src/cpus/cpu_alpha_instr.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 /trunk/src/cpus/cpu_alpha_instr.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 20 - (show annotations)
Mon Oct 8 16:19:23 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 29893 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1055 2005/11/25 22:48:36 debug Exp $
20051031	Adding disassembly support for more ARM instructions (clz,
		smul* etc), and adding a hack to support "new tiny" pages
		for StrongARM.
20051101	Minor documentation updates (NetBSD 2.0.2 -> 2.1, and OpenBSD
		3.7 -> 3.8, and lots of testing).
		Changing from 1-sector PIO mode 0 transfers to 128-sector PIO
		mode 3 (in dev_wdc).
		Various minor ARM dyntrans updates (pc-relative loads from
		within the same page as the instruction are now treated as
		constant "mov").
20051102	Re-enabling instruction combinations (they were accidentally
		disabled).
		Dyntrans TLB entries are now overwritten using a round-robin
		scheme instead of randomly. This increases performance.
		Fixing a typo in file.c (thanks to Chuan-Hua Chang for
		noticing it).
		Experimenting with adding ATAPI support to dev_wdc (to make
		emulated *BSD detect cdroms as cdroms, not harddisks).
20051104	Various minor updates.
20051105	Continuing on the ATAPI emulation. Seems to work well enough
		for a NetBSD/cats installation, but not OpenBSD/cats.
		Various other updates.
20051106	Modifying the -Y command line option to allow scaleup with
		certain graphic controllers (only dev_vga so far), not just
		scaledown.
		Some minor dyntrans cleanups.
20051107	Beginning a cleanup up the PCI subsystem (removing the
		read_register hack, etc).
20051108	Continuing the cleanup; splitting up some pci devices into a
		normal autodev device and some separate pci glue code.
20051109	Continuing on the PCI bus stuff; all old pci_*.c have been
		incorporated into normal devices and/or rewritten as glue code
		only, adding a dummy Intel 82371AB PIIX4 for Malta (not really
		tested yet).
		Minor pckbc fix so that Linux doesn't complain.
		Working on the DEC 21143 NIC (ethernet mac rom stuff mostly).
		Various other minor fixes.
20051110	Some more ARM dyntrans fine-tuning (e.g. some instruction
		combinations (cmps followed by conditional branch within the
		same page) and special cases for DPIs with regform when the
		shifter isn't used).
20051111	ARM dyntrans updates: O(n)->O(1) for just-mark-as-non-
		writable in the generic pc_to_pointers function, and some other
		minor hacks.
		Merging Cobalt and evbmips (Malta) ISA interrupt handling,
		and some minor fixes to allow Linux to accept harddisk irqs.
20051112	Minor device updates (pckbc, dec21143, lpt, ...), most
		importantly fixing the ALI M1543/M5229 so that harddisk irqs
		work with Linux/CATS.
20051113	Some more generalizations of the PCI subsystem.
		Finally took the time to add a hack for SCSI CDROM TOCs; this
		enables OpenBSD to use partition 'a' (as needed by the OpenBSD
		installer), and Windows NT's installer to get a bit further.
		Also fixing dev_wdc to allow Linux to detect ATAPI CDROMs.
		Continuing on the DEC 21143.
20051114	Minor ARM dyntrans tweaks; ARM cmps+branch optimization when
		comparing with 0, and generalizing the xchg instr. comb.
		Adding disassembly of ARM mrrc/mcrr and q{,d}{add,sub}.
20051115	Continuing on various PPC things (BATs, other address trans-
		lation things, various loads/stores, BeBox emulation, etc.).
		Beginning to work on PPC interrupt/exception support.
20051116	Factoring out some code which initializes legacy ISA devices
		from those machines that use them (bus_isa).
		Continuing on PPC interrupt/exception support.
20051117	Minor Malta fixes: RTC year offset = 80, disabling a speed hack
		which caused NetBSD to detect a too fast cpu, and adding a new
		hack to make Linux detect a faster cpu.
		Continuing on the Artesyn PM/PPC emulation mode.
		Adding an Algor emulation skeleton (P4032 and P5064);
		implementing some of the basics.
		Continuing on PPC emulation in general; usage of unimplemented
		SPRs is now easier to track, continuing on memory/exception
		related issues, etc.
20051118	More work on PPC emulation (tgpr0..3, exception handling,
		memory stuff, syscalls, etc.).
20051119	Changing the ARM dyntrans code to mostly use cpu->pc, and not
		necessarily use arm reg 15. Seems to work.
		Various PPC updates; continuing on the PReP emulation mode.
20051120	Adding a workaround/hack to dev_mc146818 to allow NetBSD/prep
		to detect the clock.
20051121	More cleanup of the PCI bus (memory and I/O bases, etc).
		Continuing on various PPC things (decrementer and timebase,
		WDCs on obio (on PReP) use irq 13, not 14/15).
20051122	Continuing on the CPC700 controller (interrupts etc) for PMPPC,
		and on PPC stuff in general.
		Finally! After some bug fixes to the virtual to physical addr
		translation, NetBSD/{prep,pmppc} 2.1 reach userland and are
		stable enough to be interacted with.
		More PCI updates; reverse-endian device access for PowerPC etc.
20051123	Generalizing the IEEE floating point subsystem (moving it out
		from src/cpus/cpu_mips_coproc.c into a new src/float_emul.c).
		Input via slave xterms was sometimes not really working; fixing
		this for ns16550, and a warning message is now displayed if
		multiple non-xterm consoles are active.
		Adding some PPC floating point support, etc.
		Various interrupt related updates (dev_wdc, _ns16550, _8259,
		and the isa32 common code in machine.c).
		NetBSD/prep can now be installed! :-) (Well, with some manual
		commands necessary before running sysinst.) Updating the
		documentation and various other things to reflect this.
20051124	Various minor documentation updates.
		Continuing the work on the DEC 21143 NIC.
20051125	LOTS of work on the 21143. Both OpenBSD and NetBSD work fine
		with it now, except that OpenBSD sometimes gives a time-out
		warning.
		Minor documentation updates.

==============  RELEASE 0.3.7  ==============


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_alpha_instr.c,v 1.3 2005/11/06 22:41:11 debug Exp $
29 *
30 * Alpha instructions.
31 *
32 * Individual functions should keep track of cpu->n_translated_instrs.
33 * (If no instruction was executed, then it should be decreased. If, say, 4
34 * instructions were combined into one function and executed, then it should
35 * be increased by 3.)
36 */
37
38
39 /*
40 * nop: Do nothing.
41 */
42 X(nop)
43 {
44 }
45
46
47 /*
48 * call_pal: PALcode call
49 *
50 * arg[0] = pal nr
51 */
52 X(call_pal)
53 {
54 /* Synchronize PC first: */
55 uint64_t old_pc, low_pc = ((size_t)ic - (size_t)
56 cpu->cd.alpha.cur_ic_page) / sizeof(struct alpha_instr_call);
57 cpu->pc &= ~((ALPHA_IC_ENTRIES_PER_PAGE-1) <<
58 ALPHA_INSTR_ALIGNMENT_SHIFT);
59 cpu->pc += (low_pc << ALPHA_INSTR_ALIGNMENT_SHIFT);
60 old_pc = cpu->pc;
61
62 alpha_palcode(cpu, ic->arg[0]);
63
64 if (!cpu->running) {
65 cpu->running_translated = 0;
66 cpu->n_translated_instrs --;
67 cpu->cd.alpha.next_ic = &nothing_call;
68 } else if (cpu->pc != old_pc) {
69 /* The PC value was changed by the palcode call. */
70 /* Find the new physical page and update the translation
71 pointers: */
72 alpha_pc_to_pointers(cpu);
73 }
74 }
75
76
77 /*
78 * jsr: Jump to SubRoutine
79 *
80 * arg[0] = ptr to uint64_t where to store return PC
81 * arg[1] = ptr to uint64_t of new PC
82 */
83 X(jsr)
84 {
85 uint64_t old_pc = cpu->pc, low_pc;
86 uint64_t mask_within_page = ((ALPHA_IC_ENTRIES_PER_PAGE-1)
87 << ALPHA_INSTR_ALIGNMENT_SHIFT) |
88 ((1 << ALPHA_INSTR_ALIGNMENT_SHIFT) - 1);
89
90 low_pc = ((size_t)ic - (size_t)
91 cpu->cd.alpha.cur_ic_page) / sizeof(struct alpha_instr_call);
92 cpu->pc &= ~((ALPHA_IC_ENTRIES_PER_PAGE-1)
93 << ALPHA_INSTR_ALIGNMENT_SHIFT);
94 cpu->pc += (low_pc << ALPHA_INSTR_ALIGNMENT_SHIFT) + 4;
95
96 *((int64_t *)ic->arg[0]) = cpu->pc;
97 cpu->pc = *((int64_t *)ic->arg[1]);
98
99 /*
100 * If this is a jump/return into the same code page as we were
101 * already in, then just set cpu->cd.alpha.next_ic.
102 */
103 if ((old_pc & ~mask_within_page) == (cpu->pc & ~mask_within_page)) {
104 cpu->cd.alpha.next_ic = cpu->cd.alpha.cur_ic_page +
105 ((cpu->pc & mask_within_page) >> 2);
106 } else {
107 /* Find the new physical page and update pointers: */
108 alpha_pc_to_pointers(cpu);
109 }
110 }
111
112
113 /*
114 * jsr_trace: Jump to SubRoutine (with function call trace enabled)
115 *
116 * Arguments same as for jsr.
117 */
118 X(jsr_trace)
119 {
120 cpu_functioncall_trace(cpu, *((int64_t *)ic->arg[1]));
121 instr(jsr)(cpu, ic);
122 }
123
124
125 /*
126 * jsr_0: JSR/RET, don't store return PC.
127 *
128 * arg[0] = ignored
129 * arg[1] = ptr to uint64_t of new PC
130 */
131 X(jsr_0)
132 {
133 uint64_t old_pc = cpu->pc;
134 uint64_t mask_within_page = ((ALPHA_IC_ENTRIES_PER_PAGE-1)
135 << ALPHA_INSTR_ALIGNMENT_SHIFT)
136 | ((1 << ALPHA_INSTR_ALIGNMENT_SHIFT) - 1);
137
138 cpu->pc = *((int64_t *)ic->arg[1]);
139
140 /*
141 * If this is a jump/return into the same code page as we were
142 * already in, then just set cpu->cd.alpha.next_ic.
143 */
144 if ((old_pc & ~mask_within_page) == (cpu->pc & ~mask_within_page)) {
145 cpu->cd.alpha.next_ic = cpu->cd.alpha.cur_ic_page +
146 ((cpu->pc & mask_within_page) >> 2);
147 } else {
148 /* Find the new physical page and update pointers: */
149 alpha_pc_to_pointers(cpu);
150 }
151 }
152
153
154 /*
155 * jsr_0_trace: JSR/RET (with function call trace enabled)
156 *
157 * Arguments same as for jsr_0.
158 */
159 X(jsr_0_trace)
160 {
161 cpu_functioncall_trace_return(cpu);
162 instr(jsr_0)(cpu, ic);
163 }
164
165
166 /*
167 * br: Branch (to a different translated page)
168 *
169 * arg[0] = relative offset (as an int32_t)
170 */
171 X(br)
172 {
173 uint64_t low_pc;
174
175 /* Calculate new PC from this instruction + arg[0] */
176 low_pc = ((size_t)ic - (size_t)
177 cpu->cd.alpha.cur_ic_page) / sizeof(struct alpha_instr_call);
178 cpu->pc &= ~((ALPHA_IC_ENTRIES_PER_PAGE-1)
179 << ALPHA_INSTR_ALIGNMENT_SHIFT);
180 cpu->pc += (low_pc << ALPHA_INSTR_ALIGNMENT_SHIFT);
181 cpu->pc += (int32_t)ic->arg[0];
182
183 /* Find the new physical page and update the translation pointers: */
184 alpha_pc_to_pointers(cpu);
185 }
186
187
188 /*
189 * br: Branch (to a different translated page), write return address
190 *
191 * arg[0] = relative offset (as an int32_t)
192 * arg[1] = pointer to uint64_t where to write return address
193 */
194 X(br_return)
195 {
196 uint64_t low_pc;
197
198 /* Calculate new PC from this instruction + arg[0] */
199 low_pc = ((size_t)ic - (size_t)
200 cpu->cd.alpha.cur_ic_page) / sizeof(struct alpha_instr_call);
201 cpu->pc &= ~((ALPHA_IC_ENTRIES_PER_PAGE-1)
202 << ALPHA_INSTR_ALIGNMENT_SHIFT);
203 cpu->pc += (low_pc << ALPHA_INSTR_ALIGNMENT_SHIFT);
204
205 /* ... but first, save away the return address: */
206 *((int64_t *)ic->arg[1]) = cpu->pc + 4;
207
208 cpu->pc += (int32_t)ic->arg[0];
209
210 /* Find the new physical page and update the translation pointers: */
211 alpha_pc_to_pointers(cpu);
212 }
213
214
215 /*
216 * beq: Branch (to a different translated page) if Equal
217 *
218 * arg[0] = relative offset (as an int32_t)
219 * arg[1] = pointer to int64_t register
220 */
221 X(beq)
222 {
223 if (*((int64_t *)ic->arg[1]) == 0)
224 instr(br)(cpu, ic);
225 }
226
227
228 /*
229 * blbs: Branch (to a different translated page) if Low Bit Set
230 *
231 * arg[0] = relative offset (as an int32_t)
232 * arg[1] = pointer to int64_t register
233 */
234 X(blbs)
235 {
236 if (*((int64_t *)ic->arg[1]) & 1)
237 instr(br)(cpu, ic);
238 }
239
240
241 /*
242 * blbc: Branch (to a different translated page) if Low Bit Clear
243 *
244 * arg[0] = relative offset (as an int32_t)
245 * arg[1] = pointer to int64_t register
246 */
247 X(blbc)
248 {
249 if (!(*((int64_t *)ic->arg[1]) & 1))
250 instr(br)(cpu, ic);
251 }
252
253
254 /*
255 * bne: Branch (to a different translated page) if Not Equal
256 *
257 * arg[0] = relative offset (as an int32_t)
258 * arg[1] = pointer to int64_t register
259 */
260 X(bne)
261 {
262 if (*((int64_t *)ic->arg[1]) != 0)
263 instr(br)(cpu, ic);
264 }
265
266
267 /*
268 * ble: Branch (to a different translated page) if Less or Equal
269 *
270 * arg[0] = relative offset (as an int32_t)
271 * arg[1] = pointer to int64_t register
272 */
273 X(ble)
274 {
275 if (*((int64_t *)ic->arg[1]) <= 0)
276 instr(br)(cpu, ic);
277 }
278
279
280 /*
281 * blt: Branch (to a different translated page) if Less Than
282 *
283 * arg[0] = relative offset (as an int32_t)
284 * arg[1] = pointer to int64_t register
285 */
286 X(blt)
287 {
288 if (*((int64_t *)ic->arg[1]) < 0)
289 instr(br)(cpu, ic);
290 }
291
292
293 /*
294 * bge: Branch (to a different translated page) if Greater or Equal
295 *
296 * arg[0] = relative offset (as an int32_t)
297 * arg[1] = pointer to int64_t register
298 */
299 X(bge)
300 {
301 if (*((int64_t *)ic->arg[1]) >= 0)
302 instr(br)(cpu, ic);
303 }
304
305
306 /*
307 * bgt: Branch (to a different translated page) if Greater Than
308 *
309 * arg[0] = relative offset (as an int32_t)
310 * arg[1] = pointer to int64_t register
311 */
312 X(bgt)
313 {
314 if (*((int64_t *)ic->arg[1]) > 0)
315 instr(br)(cpu, ic);
316 }
317
318
319 /*
320 * br_samepage: Branch (to within the same translated page)
321 *
322 * arg[0] = pointer to new alpha_instr_call
323 */
324 X(br_samepage)
325 {
326 cpu->cd.alpha.next_ic = (struct alpha_instr_call *) ic->arg[0];
327 }
328
329
330 /*
331 * br_return_samepage: Branch (to within the same translated page),
332 * and save return address
333 *
334 * arg[0] = pointer to new alpha_instr_call
335 * arg[1] = pointer to uint64_t where to store return address
336 */
337 X(br_return_samepage)
338 {
339 uint64_t low_pc;
340
341 low_pc = ((size_t)ic - (size_t)
342 cpu->cd.alpha.cur_ic_page) / sizeof(struct alpha_instr_call);
343 cpu->pc &= ~((ALPHA_IC_ENTRIES_PER_PAGE-1)
344 << ALPHA_INSTR_ALIGNMENT_SHIFT);
345 cpu->pc += (low_pc << ALPHA_INSTR_ALIGNMENT_SHIFT);
346 *((int64_t *)ic->arg[1]) = cpu->pc + 4;
347
348 cpu->cd.alpha.next_ic = (struct alpha_instr_call *) ic->arg[0];
349 }
350
351
352 /*
353 * beq_samepage: Branch (to within the same translated page) if Equal
354 *
355 * arg[0] = pointer to new alpha_instr_call
356 * arg[1] = pointer to int64_t register
357 */
358 X(beq_samepage)
359 {
360 if (*((int64_t *)ic->arg[1]) == 0)
361 instr(br_samepage)(cpu, ic);
362 }
363
364
365 /*
366 * blbs_samepage: Branch (to within the same translated page) if Low Bit Set
367 *
368 * arg[0] = pointer to new alpha_instr_call
369 * arg[1] = pointer to int64_t register
370 */
371 X(blbs_samepage)
372 {
373 if (*((int64_t *)ic->arg[1]) & 1)
374 instr(br_samepage)(cpu, ic);
375 }
376
377
378 /*
379 * blbc_samepage: Branch (to within the same translated page) if Low Bit Clear
380 *
381 * arg[0] = pointer to new alpha_instr_call
382 * arg[1] = pointer to int64_t register
383 */
384 X(blbc_samepage)
385 {
386 if (!(*((int64_t *)ic->arg[1]) & 1))
387 instr(br_samepage)(cpu, ic);
388 }
389
390
391 /*
392 * bne_samepage: Branch (to within the same translated page) if Not Equal
393 *
394 * arg[0] = pointer to new alpha_instr_call
395 * arg[1] = pointer to int64_t register
396 */
397 X(bne_samepage)
398 {
399 if (*((int64_t *)ic->arg[1]) != 0)
400 instr(br_samepage)(cpu, ic);
401 }
402
403
404 /*
405 * ble_samepage: Branch (to within the same translated page) if Less or Equal
406 *
407 * arg[0] = pointer to new alpha_instr_call
408 * arg[1] = pointer to int64_t register
409 */
410 X(ble_samepage)
411 {
412 if (*((int64_t *)ic->arg[1]) <= 0)
413 instr(br_samepage)(cpu, ic);
414 }
415
416
417 /*
418 * blt_samepage: Branch (to within the same translated page) if Less Than
419 *
420 * arg[0] = pointer to new alpha_instr_call
421 * arg[1] = pointer to int64_t register
422 */
423 X(blt_samepage)
424 {
425 if (*((int64_t *)ic->arg[1]) < 0)
426 instr(br_samepage)(cpu, ic);
427 }
428
429
430 /*
431 * bge_samepage: Branch (to within the same translated page)
432 * if Greater or Equal
433 *
434 * arg[0] = pointer to new alpha_instr_call
435 * arg[1] = pointer to int64_t register
436 */
437 X(bge_samepage)
438 {
439 if (*((int64_t *)ic->arg[1]) >= 0)
440 instr(br_samepage)(cpu, ic);
441 }
442
443
444 /*
445 * bgt_samepage: Branch (to within the same translated page) if Greater Than
446 *
447 * arg[0] = pointer to new alpha_instr_call
448 * arg[1] = pointer to int64_t register
449 */
450 X(bgt_samepage)
451 {
452 if (*((int64_t *)ic->arg[1]) > 0)
453 instr(br_samepage)(cpu, ic);
454 }
455
456
457 /*
458 * mull: Signed Multiply 32x32 => 32.
459 *
460 * arg[0] = pointer to destination uint64_t
461 * arg[1] = pointer to source uint64_t
462 * arg[2] = pointer to source uint64_t
463 */
464 X(mull)
465 {
466 int32_t a = reg(ic->arg[1]);
467 int32_t b = reg(ic->arg[2]);
468 reg(ic->arg[0]) = (int64_t)(int32_t)(a * b);
469 }
470
471
472 /*
473 * mulq: Unsigned Multiply 64x64 => 64.
474 *
475 * arg[0] = pointer to destination uint64_t
476 * arg[1] = pointer to source uint64_t
477 * arg[2] = pointer to source uint64_t
478 */
479 X(mulq)
480 {
481 reg(ic->arg[0]) = reg(ic->arg[1]) * reg(ic->arg[2]);
482 }
483
484
485 /*
486 * umulh: Unsigned Multiply 64x64 => 128. Store high part in dest reg.
487 *
488 * arg[0] = pointer to destination uint64_t
489 * arg[1] = pointer to source uint64_t
490 * arg[2] = pointer to source uint64_t
491 */
492 X(umulh)
493 {
494 uint64_t reshi = 0, reslo = 0;
495 uint64_t s1 = reg(ic->arg[1]), s2 = reg(ic->arg[2]);
496 int i, bit;
497
498 for (i=0; i<64; i++) {
499 bit = (s1 & 0x8000000000000000ULL)? 1 : 0;
500 s1 <<= 1;
501
502 /* If bit in s1 set, then add s2 to reshi/lo: */
503 if (bit) {
504 uint64_t old_reslo = reslo;
505 reslo += s2;
506 if (reslo < old_reslo)
507 reshi ++;
508 }
509
510 if (i != 63) {
511 reshi <<= 1;
512 reshi += (reslo & 0x8000000000000000ULL? 1 : 0);
513 reslo <<= 1;
514 }
515 }
516
517 reg(ic->arg[0]) = reshi;
518 }
519
520
521 /*
522 * lda: Load address.
523 *
524 * arg[0] = pointer to destination uint64_t
525 * arg[1] = pointer to source uint64_t
526 * arg[2] = offset (possibly as an int32_t)
527 */
528 X(lda)
529 {
530 reg(ic->arg[0]) = reg(ic->arg[1]) + (int64_t)(int32_t)ic->arg[2];
531 }
532
533
534 /*
535 * lda_0: Load address compared to the zero register.
536 *
537 * arg[0] = pointer to destination uint64_t
538 * arg[1] = ignored
539 * arg[2] = offset (possibly as an int32_t)
540 */
541 X(lda_0)
542 {
543 reg(ic->arg[0]) = (int64_t)(int32_t)ic->arg[2];
544 }
545
546
547 /*
548 * clear: Clear a 64-bit register.
549 *
550 * arg[0] = pointer to destination uint64_t
551 */
552 X(clear)
553 {
554 reg(ic->arg[0]) = 0;
555 }
556
557
558 /*
559 * rdcc: Read the Cycle Counter into a 64-bit register.
560 *
561 * arg[0] = pointer to destination uint64_t
562 */
563 X(rdcc)
564 {
565 reg(ic->arg[0]) = cpu->cd.alpha.pcc;
566
567 /* TODO: actually keep the pcc updated! */
568 cpu->cd.alpha.pcc += 20;
569 }
570
571
572 #include "tmp_alpha_misc.c"
573
574
575 /*****************************************************************************/
576
577
578 X(end_of_page)
579 {
580 /* Update the PC: (offset 0, but on the next page) */
581 cpu->pc &= ~((ALPHA_IC_ENTRIES_PER_PAGE-1)
582 << ALPHA_INSTR_ALIGNMENT_SHIFT);
583 cpu->pc += (ALPHA_IC_ENTRIES_PER_PAGE
584 << ALPHA_INSTR_ALIGNMENT_SHIFT);
585
586 /* Find the new physical page and update the translation pointers: */
587 alpha_pc_to_pointers(cpu);
588
589 /* end_of_page doesn't count as an executed instruction: */
590 cpu->n_translated_instrs --;
591 }
592
593
594 /*****************************************************************************/
595
596
597 /*
598 * alpha_instr_to_be_translated():
599 *
600 * Translate an instruction word into an alpha_instr_call. ic is filled in with
601 * valid data for the translated instruction, or a "nothing" instruction if
602 * there was a translation failure. The newly translated instruction is then
603 * executed.
604 */
605 X(to_be_translated)
606 {
607 uint64_t addr, low_pc;
608 uint32_t iword;
609 struct alpha_vph_page *vph_p;
610 unsigned char *page;
611 unsigned char ib[4];
612 void (*samepage_function)(struct cpu *, struct alpha_instr_call *);
613 int opcode, ra, rb, func, rc, imm, load, loadstore_type, fp, llsc;
614
615 /* Figure out the (virtual) address of the instruction: */
616 low_pc = ((size_t)ic - (size_t)cpu->cd.alpha.cur_ic_page)
617 / sizeof(struct alpha_instr_call);
618 addr = cpu->pc & ~((ALPHA_IC_ENTRIES_PER_PAGE-1) <<
619 ALPHA_INSTR_ALIGNMENT_SHIFT);
620 addr += (low_pc << ALPHA_INSTR_ALIGNMENT_SHIFT);
621 addr &= ~((1 << ALPHA_INSTR_ALIGNMENT_SHIFT) - 1);
622 cpu->pc = addr;
623
624 /* Read the instruction word from memory: */
625 if ((addr >> ALPHA_TOPSHIFT) == 0) {
626 vph_p = cpu->cd.alpha.vph_table0[(addr >>
627 ALPHA_LEVEL0_SHIFT) & 8191];
628 page = vph_p->host_load[(addr >> ALPHA_LEVEL1_SHIFT) & 8191];
629 } else if ((addr >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) {
630 vph_p = cpu->cd.alpha.vph_table0_kernel[(addr >>
631 ALPHA_LEVEL0_SHIFT) & 8191];
632 page = vph_p->host_load[(addr >> ALPHA_LEVEL1_SHIFT) & 8191];
633 } else
634 page = NULL;
635
636 if (page != NULL) {
637 /* fatal("TRANSLATION HIT!\n"); */
638 memcpy(ib, page + (addr & 8191), sizeof(ib));
639 } else {
640 /* fatal("TRANSLATION MISS!\n"); */
641 if (!cpu->memory_rw(cpu, cpu->mem, addr, &ib[0],
642 sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
643 fatal("to_be_translated(): read failed: TODO\n");
644 goto bad;
645 }
646 }
647
648 #ifdef HOST_LITTLE_ENDIAN
649 iword = *((uint32_t *)&ib[0]);
650 #else
651 iword = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24);
652 #endif
653
654 /* fatal("{ Alpha: translating pc=0x%016llx iword=0x%08x }\n",
655 (long long)addr, (int)iword); */
656
657
658 #define DYNTRANS_TO_BE_TRANSLATED_HEAD
659 #include "cpu_dyntrans.c"
660 #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
661
662
663 opcode = (iword >> 26) & 63;
664 ra = (iword >> 21) & 31;
665 rb = (iword >> 16) & 31;
666 func = (iword >> 5) & 0x7ff;
667 rc = iword & 31;
668 imm = iword & 0xffff;
669
670 switch (opcode) {
671 case 0x00: /* CALL_PAL */
672 ic->f = instr(call_pal);
673 ic->arg[0] = (size_t) (iword & 0x3ffffff);
674 break;
675 case 0x08: /* LDA */
676 case 0x09: /* LDAH */
677 if (ra == ALPHA_ZERO) {
678 ic->f = instr(nop);
679 break;
680 }
681 /* TODO: A special case which is common is to add or subtract
682 a small offset from sp. */
683 ic->f = instr(lda);
684 ic->arg[0] = (size_t) &cpu->cd.alpha.r[ra];
685 ic->arg[1] = (size_t) &cpu->cd.alpha.r[rb];
686 if (rb == ALPHA_ZERO)
687 ic->f = instr(lda_0);
688 ic->arg[2] = (ssize_t)(int16_t)imm;
689 if (opcode == 0x09)
690 ic->arg[2] <<= 16;
691 break;
692 case 0x0b: /* LDQ_U */
693 case 0x0f: /* STQ_U */
694 if (ra == ALPHA_ZERO && opcode == 0x0b) {
695 ic->f = instr(nop);
696 break;
697 }
698 if (opcode == 0x0b)
699 ic->f = instr(ldq_u);
700 else
701 ic->f = instr(stq_u);
702 ic->arg[0] = (size_t) &cpu->cd.alpha.r[ra];
703 ic->arg[1] = (size_t) &cpu->cd.alpha.r[rb];
704 ic->arg[2] = (ssize_t)(int16_t)imm;
705 break;
706 case 0x0a:
707 case 0x0c:
708 case 0x0d:
709 case 0x0e:
710 case 0x22:
711 case 0x23:
712 case 0x26:
713 case 0x27:
714 case 0x28:
715 case 0x29:
716 case 0x2a:
717 case 0x2b:
718 case 0x2c:
719 case 0x2d:
720 case 0x2e:
721 case 0x2f:
722 loadstore_type = 0; fp = 0; load = 0; llsc = 0;
723 switch (opcode) {
724 case 0x0a: loadstore_type = 0; load = 1; break; /* ldbu */
725 case 0x0c: loadstore_type = 1; load = 1; break; /* ldwu */
726 case 0x0d: loadstore_type = 1; break; /* stw */
727 case 0x0e: loadstore_type = 0; break; /* stb */
728 case 0x22: loadstore_type = 2; load = 1; fp = 1; break; /*lds*/
729 case 0x23: loadstore_type = 3; load = 1; fp = 1; break; /*ldt*/
730 case 0x26: loadstore_type = 2; fp = 1; break; /* sts */
731 case 0x27: loadstore_type = 3; fp = 1; break; /* stt */
732 case 0x28: loadstore_type = 2; load = 1; break; /* ldl */
733 case 0x29: loadstore_type = 3; load = 1; break; /* ldq */
734 case 0x2a: loadstore_type = 2; load = llsc = 1; break;/* ldl_l*/
735 case 0x2b: loadstore_type = 3; load = llsc = 1; break;/* ldq_l*/
736 case 0x2c: loadstore_type = 2; break; /* stl */
737 case 0x2d: loadstore_type = 3; break; /* stq */
738 case 0x2e: loadstore_type = 2; llsc = 1; break; /* stl_c */
739 case 0x2f: loadstore_type = 3; llsc = 1; break; /* stq_c */
740 }
741 ic->f = alpha_loadstore[
742 loadstore_type + (imm==0? 4 : 0) + 8 * load
743 + (cpu->machine->dyntrans_alignment_check? 16:0)
744 + 32 * llsc];
745 /* Load to the zero register is treated as a prefetch
746 hint. It is ignored here. */
747 if (load && ra == ALPHA_ZERO) {
748 ic->f = instr(nop);
749 break;
750 }
751 if (fp)
752 ic->arg[0] = (size_t) &cpu->cd.alpha.f[ra];
753 else
754 ic->arg[0] = (size_t) &cpu->cd.alpha.r[ra];
755 ic->arg[1] = (size_t) &cpu->cd.alpha.r[rb];
756 ic->arg[2] = (ssize_t)(int16_t)imm;
757 break;
758 case 0x10:
759 if (rc == ALPHA_ZERO) {
760 ic->f = instr(nop);
761 break;
762 }
763 ic->arg[0] = (size_t) &cpu->cd.alpha.r[rc];
764 ic->arg[1] = (size_t) &cpu->cd.alpha.r[ra];
765 if (func & 0x80)
766 ic->arg[2] = (size_t)((rb << 3) + (func >> 8));
767 else
768 ic->arg[2] = (size_t) &cpu->cd.alpha.r[rb];
769 switch (func & 0xff) {
770 case 0x00: ic->f = instr(addl); break;
771 case 0x02: ic->f = instr(s4addl); break;
772 case 0x09: ic->f = instr(subl); break;
773 case 0x0b: ic->f = instr(s4subl); break;
774 case 0x12: ic->f = instr(s8addl); break;
775 case 0x1b: ic->f = instr(s8subl); break;
776 case 0x1d: ic->f = instr(cmpult); break;
777 case 0x20: ic->f = instr(addq); break;
778 case 0x22: ic->f = instr(s4addq); break;
779 case 0x29: ic->f = instr(subq); break;
780 case 0x2b: ic->f = instr(s4subq); break;
781 case 0x2d: ic->f = instr(cmpeq); break;
782 case 0x32: ic->f = instr(s8addq); break;
783 case 0x3b: ic->f = instr(s8subq); break;
784 case 0x3d: ic->f = instr(cmpule); break;
785 case 0x4d: ic->f = instr(cmplt); break;
786 case 0x6d: ic->f = instr(cmple); break;
787
788 case 0x80: ic->f = instr(addl_imm); break;
789 case 0x82: ic->f = instr(s4addl_imm); break;
790 case 0x89: ic->f = instr(subl_imm); break;
791 case 0x8b: ic->f = instr(s4subl_imm); break;
792 case 0x92: ic->f = instr(s8addl_imm); break;
793 case 0x9b: ic->f = instr(s8subl_imm); break;
794 case 0x9d: ic->f = instr(cmpult_imm); break;
795 case 0xa0: ic->f = instr(addq_imm); break;
796 case 0xa2: ic->f = instr(s4addq_imm); break;
797 case 0xa9: ic->f = instr(subq_imm); break;
798 case 0xab: ic->f = instr(s4subq_imm); break;
799 case 0xad: ic->f = instr(cmpeq_imm); break;
800 case 0xb2: ic->f = instr(s8addq_imm); break;
801 case 0xbb: ic->f = instr(s8subq_imm); break;
802 case 0xbd: ic->f = instr(cmpule_imm); break;
803 case 0xcd: ic->f = instr(cmplt_imm); break;
804 case 0xed: ic->f = instr(cmple_imm); break;
805
806 default:fatal("[ Alpha: unimplemented function 0x%03x for"
807 " opcode 0x%02x ]\n", func, opcode);
808 goto bad;
809 }
810 break;
811 case 0x11:
812 if (rc == ALPHA_ZERO) {
813 ic->f = instr(nop);
814 break;
815 }
816 ic->arg[0] = (size_t) &cpu->cd.alpha.r[rc];
817 ic->arg[1] = (size_t) &cpu->cd.alpha.r[ra];
818 if (func & 0x80)
819 ic->arg[2] = (size_t)((rb << 3) + (func >> 8));
820 else
821 ic->arg[2] = (size_t) &cpu->cd.alpha.r[rb];
822 switch (func & 0xff) {
823 case 0x00: ic->f = instr(and); break;
824 case 0x08: ic->f = instr(andnot); break;
825 case 0x14: ic->f = instr(cmovlbs); break;
826 case 0x16: ic->f = instr(cmovlbc); break;
827 case 0x20: ic->f = instr(or);
828 if (ra == ALPHA_ZERO || rb == ALPHA_ZERO) {
829 if (ra == ALPHA_ZERO)
830 ra = rb;
831 ic->f = alpha_mov_r_r[ra + rc*32];
832 }
833 break;
834 case 0x24: ic->f = instr(cmoveq); break;
835 case 0x26: ic->f = instr(cmovne); break;
836 case 0x28: ic->f = instr(ornot); break;
837 case 0x40: ic->f = instr(xor); break;
838 case 0x44: ic->f = instr(cmovlt); break;
839 case 0x46: ic->f = instr(cmovge); break;
840 case 0x48: ic->f = instr(xornot); break;
841 case 0x64: ic->f = instr(cmovle); break;
842 case 0x66: ic->f = instr(cmovgt); break;
843 case 0x80: ic->f = instr(and_imm); break;
844 case 0x88: ic->f = instr(andnot_imm); break;
845 case 0x94: ic->f = instr(cmovlbs_imm); break;
846 case 0x96: ic->f = instr(cmovlbc_imm); break;
847 case 0xa0: ic->f = instr(or_imm); break;
848 case 0xa4: ic->f = instr(cmoveq_imm); break;
849 case 0xa6: ic->f = instr(cmovne_imm); break;
850 case 0xa8: ic->f = instr(ornot_imm); break;
851 case 0xc0: ic->f = instr(xor_imm); break;
852 case 0xc4: ic->f = instr(cmovlt_imm); break;
853 case 0xc6: ic->f = instr(cmovge_imm); break;
854 case 0xc8: ic->f = instr(xornot_imm); break;
855 case 0xe4: ic->f = instr(cmovle_imm); break;
856 case 0xe6: ic->f = instr(cmovgt_imm); break;
857 default:fatal("[ Alpha: unimplemented function 0x%03x for"
858 " opcode 0x%02x ]\n", func, opcode);
859 goto bad;
860 }
861 break;
862 case 0x12:
863 if (rc == ALPHA_ZERO) {
864 ic->f = instr(nop);
865 break;
866 }
867 ic->arg[0] = (size_t) &cpu->cd.alpha.r[rc];
868 ic->arg[1] = (size_t) &cpu->cd.alpha.r[ra];
869 if (func & 0x80)
870 ic->arg[2] = (size_t)((rb << 3) + (func >> 8));
871 else
872 ic->arg[2] = (size_t) &cpu->cd.alpha.r[rb];
873 switch (func & 0xff) {
874 case 0x02: ic->f = instr(mskbl); break;
875 case 0x06: ic->f = instr(extbl); break;
876 case 0x0b: ic->f = instr(insbl); break;
877 case 0x12: ic->f = instr(mskwl); break;
878 case 0x16: ic->f = instr(extwl); break;
879 case 0x1b: ic->f = instr(inswl); break;
880 case 0x22: ic->f = instr(mskll); break;
881 case 0x26: ic->f = instr(extll); break;
882 case 0x2b: ic->f = instr(insll); break;
883 case 0x30: ic->f = instr(zap); break;
884 case 0x31: ic->f = instr(zapnot); break;
885 case 0x32: ic->f = instr(mskql); break;
886 case 0x34: ic->f = instr(srl); break;
887 case 0x36: ic->f = instr(extql); break;
888 case 0x39: ic->f = instr(sll); break;
889 case 0x3b: ic->f = instr(insql); break;
890 case 0x3c: ic->f = instr(sra); break;
891 case 0x52: ic->f = instr(mskwh); break;
892 case 0x57: ic->f = instr(inswh); break;
893 case 0x5a: ic->f = instr(extwh); break;
894 case 0x62: ic->f = instr(msklh); break;
895 case 0x67: ic->f = instr(inslh); break;
896 case 0x6a: ic->f = instr(extlh); break;
897 case 0x72: ic->f = instr(mskqh); break;
898 case 0x77: ic->f = instr(insqh); break;
899 case 0x7a: ic->f = instr(extqh); break;
900 case 0x82: ic->f = instr(mskbl_imm); break;
901 case 0x86: ic->f = instr(extbl_imm); break;
902 case 0x8b: ic->f = instr(insbl_imm); break;
903 case 0x92: ic->f = instr(mskwl_imm); break;
904 case 0x96: ic->f = instr(extwl_imm); break;
905 case 0x9b: ic->f = instr(inswl_imm); break;
906 case 0xa2: ic->f = instr(mskll_imm); break;
907 case 0xa6: ic->f = instr(extll_imm); break;
908 case 0xab: ic->f = instr(insll_imm); break;
909 case 0xb0: ic->f = instr(zap_imm); break;
910 case 0xb1: ic->f = instr(zapnot_imm); break;
911 case 0xb2: ic->f = instr(mskql_imm); break;
912 case 0xb4: ic->f = instr(srl_imm); break;
913 case 0xb6: ic->f = instr(extql_imm); break;
914 case 0xb9: ic->f = instr(sll_imm); break;
915 case 0xbb: ic->f = instr(insql_imm); break;
916 case 0xbc: ic->f = instr(sra_imm); break;
917 case 0xd2: ic->f = instr(mskwh_imm); break;
918 case 0xd7: ic->f = instr(inswh_imm); break;
919 case 0xda: ic->f = instr(extwh_imm); break;
920 case 0xe2: ic->f = instr(msklh_imm); break;
921 case 0xe7: ic->f = instr(inslh_imm); break;
922 case 0xea: ic->f = instr(extlh_imm); break;
923 case 0xf2: ic->f = instr(mskqh_imm); break;
924 case 0xf7: ic->f = instr(insqh_imm); break;
925 case 0xfa: ic->f = instr(extqh_imm); break;
926 default:fatal("[ Alpha: unimplemented function 0x%03x for"
927 " opcode 0x%02x ]\n", func, opcode);
928 goto bad;
929 }
930 break;
931 case 0x13:
932 if (rc == ALPHA_ZERO) {
933 ic->f = instr(nop);
934 break;
935 }
936 ic->arg[0] = (size_t) &cpu->cd.alpha.r[rc];
937 ic->arg[1] = (size_t) &cpu->cd.alpha.r[ra];
938 if (func & 0x80)
939 ic->arg[2] = (size_t)((rb << 3) + (func >> 8));
940 else
941 ic->arg[2] = (size_t) &cpu->cd.alpha.r[rb];
942 switch (func & 0xff) {
943 case 0x00: ic->f = instr(mull); break;
944 case 0x20: ic->f = instr(mulq); break;
945 case 0x30: ic->f = instr(umulh); break;
946 default:fatal("[ Alpha: unimplemented function 0x%03x for"
947 " opcode 0x%02x ]\n", func, opcode);
948 goto bad;
949 }
950 break;
951 case 0x16:
952 if (rc == ALPHA_ZERO) {
953 ic->f = instr(nop);
954 break;
955 }
956 ic->arg[0] = (size_t) &cpu->cd.alpha.f[rc];
957 ic->arg[1] = (size_t) &cpu->cd.alpha.f[ra];
958 ic->arg[2] = (size_t) &cpu->cd.alpha.f[rb];
959 switch (func & 0x7ff) {
960 default:fatal("[ Alpha: unimplemented function 0x%03x for"
961 " opcode 0x%02x ]\n", func, opcode);
962 goto bad;
963 }
964 break;
965 case 0x17:
966 if (rc == ALPHA_ZERO) {
967 ic->f = instr(nop);
968 break;
969 }
970 ic->arg[0] = (size_t) &cpu->cd.alpha.f[rc];
971 ic->arg[1] = (size_t) &cpu->cd.alpha.f[ra];
972 ic->arg[2] = (size_t) &cpu->cd.alpha.f[rb];
973 switch (func & 0x7ff) {
974 case 0x020:
975 /* fclr: */
976 if (ra == 31 && rb == 31)
977 ic->f = instr(clear);
978 else {
979 /* fabs: */
980 goto bad;
981 }
982 break;
983 default:fatal("[ Alpha: unimplemented function 0x%03x for"
984 " opcode 0x%02x ]\n", func, opcode);
985 goto bad;
986 }
987 break;
988 case 0x18:
989 switch (iword & 0xffff) {
990 case 0x4000: /* mb */
991 case 0x4400: /* wmb */
992 ic->f = instr(nop);
993 break;
994 case 0xc000: /* rdcc ra */
995 if (ra == ALPHA_ZERO) {
996 ic->f = instr(nop);
997 break;
998 }
999 ic->arg[0] = (size_t) &cpu->cd.alpha.r[ra];
1000 ic->f = instr(rdcc);
1001 break;
1002 default:fatal("[ Alpha: unimplemented function 0x%03x for"
1003 " opcode 0x%02x ]\n", func, opcode);
1004 goto bad;
1005 }
1006 break;
1007 case 0x1a:
1008 switch ((iword >> 14) & 3) {
1009 case 0: /* JMP */
1010 case 1: /* JSR */
1011 case 2: /* RET */
1012 ic->arg[0] = (size_t) &cpu->cd.alpha.r[ra];
1013 ic->arg[1] = (size_t) &cpu->cd.alpha.r[rb];
1014 if (ra == ALPHA_ZERO) {
1015 if (cpu->machine->show_trace_tree &&
1016 rb == ALPHA_RA)
1017 ic->f = instr(jsr_0_trace);
1018 else
1019 ic->f = instr(jsr_0);
1020 } else {
1021 if (cpu->machine->show_trace_tree)
1022 ic->f = instr(jsr_trace);
1023 else
1024 ic->f = instr(jsr);
1025 }
1026 break;
1027 default:fatal("[ Alpha: unimpl JSR type %i, ra=%i rb=%i ]\n",
1028 ((iword >> 14) & 3), ra, rb);
1029 goto bad;
1030 }
1031 break;
1032 case 0x30: /* BR */
1033 case 0x34: /* BSR */
1034 case 0x38: /* BLBC */
1035 case 0x39: /* BEQ */
1036 case 0x3a: /* BLT */
1037 case 0x3b: /* BLE */
1038 case 0x3c: /* BLBS */
1039 case 0x3d: /* BNE */
1040 case 0x3e: /* BGE */
1041 case 0x3f: /* BGT */
1042 /* To avoid a GCC warning: */
1043 samepage_function = instr(nop);
1044 switch (opcode) {
1045 case 0x30:
1046 case 0x34:
1047 ic->f = instr(br);
1048 samepage_function = instr(br_samepage);
1049 if (ra != ALPHA_ZERO) {
1050 ic->f = instr(br_return);
1051 samepage_function = instr(br_return_samepage);
1052 }
1053 break;
1054 case 0x38:
1055 ic->f = instr(blbc);
1056 samepage_function = instr(blbc_samepage);
1057 break;
1058 case 0x39:
1059 ic->f = instr(beq);
1060 samepage_function = instr(beq_samepage);
1061 break;
1062 case 0x3a:
1063 ic->f = instr(blt);
1064 samepage_function = instr(blt_samepage);
1065 break;
1066 case 0x3b:
1067 ic->f = instr(ble);
1068 samepage_function = instr(ble_samepage);
1069 break;
1070 case 0x3c:
1071 ic->f = instr(blbs);
1072 samepage_function = instr(blbs_samepage);
1073 break;
1074 case 0x3d:
1075 ic->f = instr(bne);
1076 samepage_function = instr(bne_samepage);
1077 break;
1078 case 0x3e:
1079 ic->f = instr(bge);
1080 samepage_function = instr(bge_samepage);
1081 break;
1082 case 0x3f:
1083 ic->f = instr(bgt);
1084 samepage_function = instr(bgt_samepage);
1085 break;
1086 }
1087 ic->arg[1] = (size_t) &cpu->cd.alpha.r[ra];
1088 ic->arg[0] = (iword & 0x001fffff) << 2;
1089 /* Sign-extend: */
1090 if (ic->arg[0] & 0x00400000)
1091 ic->arg[0] |= 0xffffffffff800000ULL;
1092 /* Branches are calculated as PC + 4 + offset. */
1093 ic->arg[0] = (size_t)(ic->arg[0] + 4);
1094 /* Special case: branch within the same page: */
1095 {
1096 uint64_t mask_within_page =
1097 ((ALPHA_IC_ENTRIES_PER_PAGE-1) << 2) | 3;
1098 uint64_t old_pc = addr;
1099 uint64_t new_pc = old_pc + (int32_t)ic->arg[0];
1100 if ((old_pc & ~mask_within_page) ==
1101 (new_pc & ~mask_within_page)) {
1102 ic->f = samepage_function;
1103 ic->arg[0] = (size_t) (
1104 cpu->cd.alpha.cur_ic_page +
1105 ((new_pc & mask_within_page) >> 2));
1106 }
1107 }
1108 break;
1109 default:fatal("[ UNIMPLEMENTED Alpha opcode 0x%x ]\n", opcode);
1110 goto bad;
1111 }
1112
1113
1114 #define DYNTRANS_TO_BE_TRANSLATED_TAIL
1115 #include "cpu_dyntrans.c"
1116 #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
1117 }
1118

  ViewVC Help
Powered by ViewVC 1.1.26