/[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

Annotation of /trunk/src/cpus/cpu_alpha_instr.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 20 - (hide 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 dpavlin 14 /*
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 dpavlin 20 * $Id: cpu_alpha_instr.c,v 1.3 2005/11/06 22:41:11 debug Exp $
29 dpavlin 14 *
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