/[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 14 - (hide annotations)
Mon Oct 8 16:18:51 2007 UTC (13 years, 3 months ago) by dpavlin
File MIME type: text/plain
File size: 30331 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.982 2005/10/07 22:45:32 debug Exp $
20050816	Some success in decoding the way the SGI O2 PROM draws graphics
		during bootup; lines/rectangles and bitmaps work, enough to
		show the bootlogo etc. :-)
		Adding more PPC instructions, and (dummy) BAT registers.
20050817	Updating the pckbc to support scancode type 3 keyboards
		(required in order to interact with the SGI O2 PROM).
		Adding more PPC instructions.
20050818	Adding more ARM instructions; general register forms.
		Importing armreg.h from NetBSD (ARM cpu ids). Adding a (dummy)
		CATS machine mode (using SA110 as the default CPU).
		Continuing on general dyntrans related stuff.
20050819	Register forms for ARM load/stores. Gaah! The Compaq C Compiler
		bug is triggered for ARM loads as well, not just PPC :-(
		Adding full support for ARM PC-relative load/stores, and load/
		stores where the PC register is the destination register.
		Adding support for ARM a.out binaries.
20050820	Continuing to add more ARM instructions, and correcting some
		bugs. Continuing on CATS emulation.
		More work on the PPC stuff.
20050821	Minor PPC and ARM updates. Adding more machine types.
20050822	All ARM "data processing instructions" are now generated
		automatically.
20050824	Beginning the work on the ARM system control coprocessor.
		Adding support for ARM halfword load/stores, and signed loads.
20050825	Fixing an important bug related to the ARM condition codes.
		OpenBSD/zaurus and NetBSD/netwinder now print some boot
		messages. :)
		Adding a dummy SH (Hitachi SuperH) cpu family.
		Beginning to add some ARM virtual address translation.
		MIPS bugfixes: unaligned PC now cause an ADEL exception (at
		least for non-bintrans execution), and ADEL/ADES (not
		TLBL/TLBS) are used if userland tries to access kernel space.
		(Thanks to Joshua Wise for making me aware of these bugs.)
20050827	More work on the ARM emulation, and various other updates.
20050828	More ARM updates.
		Finally taking the time to work on translation invalidation
		(i.e. invalidating translated code mappings when memory is
		written to). Hopefully this doesn't break anything.
20050829	Moving CPU related files from src/ to a new subdir, src/cpus/.
		Moving PROM emulation stuff from src/ to src/promemul/.
		Better debug instruction trace for ARM loads and stores.
20050830	Various ARM updates (correcting CMP flag calculation, etc).
20050831	PPC instruction updates. (Flag fixes, etc.)
20050901	Various minor PPC and ARM instruction emulation updates.
		Minor OpenFirmware emulation updates.
20050903	Adding support for adding arbitrary ARM coprocessors (with
		the i80321 I/O coprocessor as a first test).
		Various other ARM and PPC updates.
20050904	Adding some SHcompact disassembly routines.
20050907	(Re)adding a dummy HPPA CPU module, and a dummy i960 module.
20050908	Began hacking on some Apple Partition Table support.
20050909	Adding support for loading Mach-O (Darwin PPC) binaries.
20050910	Fixing an ARM bug (Carry flag was incorrectly updated for some
		data processing instructions); OpenBSD/cats and NetBSD/
		netwinder get quite a bit further now.
		Applying a patch to dev_wdc, and a one-liner to dev_pcic, to
		make them work better when emulating new versions of OpenBSD.
		(Thanks to Alexander Yurchenko for the patches.)
		Also doing some other minor updates to dev_wdc. (Some cleanup,
		and finally converting to devinit, etc.)
20050912	IRIX doesn't have u_int64_t by default (noticed by Andreas
		<avr@gnulinux.nl>); configure updated to reflect this.
		Working on ARM register bank switching, CPSR vs SPSR issues,
		and beginning the work on interrupt/exception support.
20050913	Various minor ARM updates (speeding up load/store multiple,
		and fixing a ROR bug in R(); NetBSD/cats now boots as far as
		OpenBSD/cats).
20050917	Adding a dummy Atmel AVR (8-bit) cpu family skeleton.
20050918	Various minor updates.
20050919	Symbols are now loaded from Mach-O executables.
		Continuing the work on adding ARM exception support.
20050920	More work on ARM stuff: OpenBSD/cats and NetBSD/cats reach
		userland! :-)
20050921	Some more progress on ARM interrupt specifics.
20050923	Fixing linesize for VR4121 (patch by Yurchenko). Also fixing
		linesizes/cachesizes for some other VR4xxx.
		Adding a dummy Acer Labs M1543 PCI-ISA bridge (for CATS) and a
		dummy Symphony Labs 83C553 bridge (for Netwinder), usable by 
		dev_footbridge.
20050924	Some PPC progress.
20050925	More PPC progress.
20050926	PPC progress (fixing some bugs etc); Darwin's kernel gets
		slightly further than before.
20050928	Various updates: footbridge/ISA/pciide stuff, and finally
		fixing the VGA text scroll-by-changing-the-base-offset bug.
20050930	Adding a dummy S3 ViRGE pci card for CATS emulation, which
		both NetBSD and OpenBSD detects as VGA.
		Continuing on Footbridge (timers, ISA interrupt stuff).
20051001	Continuing... there are still bugs, probably interrupt-
		related.
20051002	More work on the Footbridge (interrupt stuff).
20051003	Various minor updates. (Trying to find the bug(s).)
20051004	Continuing on the ARM stuff.
20051005	More ARM-related fixes.
20051007	FINALLY! Found and fixed 2 ARM bugs: 1 memory related, and the
		other was because of an error in the ARM manual (load multiple
		with the S-bit set should _NOT_ load usermode registers, as the
		manual says, but it should load saved registers, which may or
		may not happen to be usermode registers).
		NetBSD/cats and OpenBSD/cats seem to install fine now :-)
		except for a minor bug at the end of the OpenBSD/cats install.
		Updating the documentation, preparing for the next release.
20051008	Continuing with release testing and cleanup.

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     * $Id: cpu_alpha_instr.c,v 1.2 2005/09/17 17:14:27 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_combine_instructions():
599     *
600     * Combine two or more instructions, if possible, into a single function call.
601     */
602     void alpha_combine_instructions(struct cpu *cpu, struct alpha_instr_call *ic,
603     uint64_t addr)
604     {
605     int n_back;
606     n_back = (addr >> 2) & (ALPHA_IC_ENTRIES_PER_PAGE-1);
607    
608     if (n_back >= 1) {
609     }
610    
611     /* TODO: Combine forward as well */
612     }
613    
614    
615     /*****************************************************************************/
616    
617    
618     /*
619     * alpha_instr_to_be_translated():
620     *
621     * Translate an instruction word into an alpha_instr_call. ic is filled in with
622     * valid data for the translated instruction, or a "nothing" instruction if
623     * there was a translation failure. The newly translated instruction is then
624     * executed.
625     */
626     X(to_be_translated)
627     {
628     uint64_t addr, low_pc;
629     uint32_t iword;
630     struct alpha_vph_page *vph_p;
631     unsigned char *page;
632     unsigned char ib[4];
633     void (*samepage_function)(struct cpu *, struct alpha_instr_call *);
634     int opcode, ra, rb, func, rc, imm, load, loadstore_type, fp, llsc;
635    
636     /* Figure out the (virtual) address of the instruction: */
637     low_pc = ((size_t)ic - (size_t)cpu->cd.alpha.cur_ic_page)
638     / sizeof(struct alpha_instr_call);
639     addr = cpu->pc & ~((ALPHA_IC_ENTRIES_PER_PAGE-1) <<
640     ALPHA_INSTR_ALIGNMENT_SHIFT);
641     addr += (low_pc << ALPHA_INSTR_ALIGNMENT_SHIFT);
642     addr &= ~((1 << ALPHA_INSTR_ALIGNMENT_SHIFT) - 1);
643     cpu->pc = addr;
644    
645     /* Read the instruction word from memory: */
646     if ((addr >> ALPHA_TOPSHIFT) == 0) {
647     vph_p = cpu->cd.alpha.vph_table0[(addr >>
648     ALPHA_LEVEL0_SHIFT) & 8191];
649     page = vph_p->host_load[(addr >> ALPHA_LEVEL1_SHIFT) & 8191];
650     } else if ((addr >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) {
651     vph_p = cpu->cd.alpha.vph_table0_kernel[(addr >>
652     ALPHA_LEVEL0_SHIFT) & 8191];
653     page = vph_p->host_load[(addr >> ALPHA_LEVEL1_SHIFT) & 8191];
654     } else
655     page = NULL;
656    
657     if (page != NULL) {
658     /* fatal("TRANSLATION HIT!\n"); */
659     memcpy(ib, page + (addr & 8191), sizeof(ib));
660     } else {
661     /* fatal("TRANSLATION MISS!\n"); */
662     if (!cpu->memory_rw(cpu, cpu->mem, addr, &ib[0],
663     sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
664     fatal("to_be_translated(): read failed: TODO\n");
665     goto bad;
666     }
667     }
668    
669     #ifdef HOST_LITTLE_ENDIAN
670     iword = *((uint32_t *)&ib[0]);
671     #else
672     iword = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24);
673     #endif
674    
675     /* fatal("{ Alpha: translating pc=0x%016llx iword=0x%08x }\n",
676     (long long)addr, (int)iword); */
677    
678    
679     #define DYNTRANS_TO_BE_TRANSLATED_HEAD
680     #include "cpu_dyntrans.c"
681     #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
682    
683    
684     opcode = (iword >> 26) & 63;
685     ra = (iword >> 21) & 31;
686     rb = (iword >> 16) & 31;
687     func = (iword >> 5) & 0x7ff;
688     rc = iword & 31;
689     imm = iword & 0xffff;
690    
691     switch (opcode) {
692     case 0x00: /* CALL_PAL */
693     ic->f = instr(call_pal);
694     ic->arg[0] = (size_t) (iword & 0x3ffffff);
695     break;
696     case 0x08: /* LDA */
697     case 0x09: /* LDAH */
698     if (ra == ALPHA_ZERO) {
699     ic->f = instr(nop);
700     break;
701     }
702     /* TODO: A special case which is common is to add or subtract
703     a small offset from sp. */
704     ic->f = instr(lda);
705     ic->arg[0] = (size_t) &cpu->cd.alpha.r[ra];
706     ic->arg[1] = (size_t) &cpu->cd.alpha.r[rb];
707     if (rb == ALPHA_ZERO)
708     ic->f = instr(lda_0);
709     ic->arg[2] = (ssize_t)(int16_t)imm;
710     if (opcode == 0x09)
711     ic->arg[2] <<= 16;
712     break;
713     case 0x0b: /* LDQ_U */
714     case 0x0f: /* STQ_U */
715     if (ra == ALPHA_ZERO && opcode == 0x0b) {
716     ic->f = instr(nop);
717     break;
718     }
719     if (opcode == 0x0b)
720     ic->f = instr(ldq_u);
721     else
722     ic->f = instr(stq_u);
723     ic->arg[0] = (size_t) &cpu->cd.alpha.r[ra];
724     ic->arg[1] = (size_t) &cpu->cd.alpha.r[rb];
725     ic->arg[2] = (ssize_t)(int16_t)imm;
726     break;
727     case 0x0a:
728     case 0x0c:
729     case 0x0d:
730     case 0x0e:
731     case 0x22:
732     case 0x23:
733     case 0x26:
734     case 0x27:
735     case 0x28:
736     case 0x29:
737     case 0x2a:
738     case 0x2b:
739     case 0x2c:
740     case 0x2d:
741     case 0x2e:
742     case 0x2f:
743     loadstore_type = 0; fp = 0; load = 0; llsc = 0;
744     switch (opcode) {
745     case 0x0a: loadstore_type = 0; load = 1; break; /* ldbu */
746     case 0x0c: loadstore_type = 1; load = 1; break; /* ldwu */
747     case 0x0d: loadstore_type = 1; break; /* stw */
748     case 0x0e: loadstore_type = 0; break; /* stb */
749     case 0x22: loadstore_type = 2; load = 1; fp = 1; break; /*lds*/
750     case 0x23: loadstore_type = 3; load = 1; fp = 1; break; /*ldt*/
751     case 0x26: loadstore_type = 2; fp = 1; break; /* sts */
752     case 0x27: loadstore_type = 3; fp = 1; break; /* stt */
753     case 0x28: loadstore_type = 2; load = 1; break; /* ldl */
754     case 0x29: loadstore_type = 3; load = 1; break; /* ldq */
755     case 0x2a: loadstore_type = 2; load = llsc = 1; break;/* ldl_l*/
756     case 0x2b: loadstore_type = 3; load = llsc = 1; break;/* ldq_l*/
757     case 0x2c: loadstore_type = 2; break; /* stl */
758     case 0x2d: loadstore_type = 3; break; /* stq */
759     case 0x2e: loadstore_type = 2; llsc = 1; break; /* stl_c */
760     case 0x2f: loadstore_type = 3; llsc = 1; break; /* stq_c */
761     }
762     ic->f = alpha_loadstore[
763     loadstore_type + (imm==0? 4 : 0) + 8 * load
764     + (cpu->machine->dyntrans_alignment_check? 16:0)
765     + 32 * llsc];
766     /* Load to the zero register is treated as a prefetch
767     hint. It is ignored here. */
768     if (load && ra == ALPHA_ZERO) {
769     ic->f = instr(nop);
770     break;
771     }
772     if (fp)
773     ic->arg[0] = (size_t) &cpu->cd.alpha.f[ra];
774     else
775     ic->arg[0] = (size_t) &cpu->cd.alpha.r[ra];
776     ic->arg[1] = (size_t) &cpu->cd.alpha.r[rb];
777     ic->arg[2] = (ssize_t)(int16_t)imm;
778     break;
779     case 0x10:
780     if (rc == ALPHA_ZERO) {
781     ic->f = instr(nop);
782     break;
783     }
784     ic->arg[0] = (size_t) &cpu->cd.alpha.r[rc];
785     ic->arg[1] = (size_t) &cpu->cd.alpha.r[ra];
786     if (func & 0x80)
787     ic->arg[2] = (size_t)((rb << 3) + (func >> 8));
788     else
789     ic->arg[2] = (size_t) &cpu->cd.alpha.r[rb];
790     switch (func & 0xff) {
791     case 0x00: ic->f = instr(addl); break;
792     case 0x02: ic->f = instr(s4addl); break;
793     case 0x09: ic->f = instr(subl); break;
794     case 0x0b: ic->f = instr(s4subl); break;
795     case 0x12: ic->f = instr(s8addl); break;
796     case 0x1b: ic->f = instr(s8subl); break;
797     case 0x1d: ic->f = instr(cmpult); break;
798     case 0x20: ic->f = instr(addq); break;
799     case 0x22: ic->f = instr(s4addq); break;
800     case 0x29: ic->f = instr(subq); break;
801     case 0x2b: ic->f = instr(s4subq); break;
802     case 0x2d: ic->f = instr(cmpeq); break;
803     case 0x32: ic->f = instr(s8addq); break;
804     case 0x3b: ic->f = instr(s8subq); break;
805     case 0x3d: ic->f = instr(cmpule); break;
806     case 0x4d: ic->f = instr(cmplt); break;
807     case 0x6d: ic->f = instr(cmple); break;
808    
809     case 0x80: ic->f = instr(addl_imm); break;
810     case 0x82: ic->f = instr(s4addl_imm); break;
811     case 0x89: ic->f = instr(subl_imm); break;
812     case 0x8b: ic->f = instr(s4subl_imm); break;
813     case 0x92: ic->f = instr(s8addl_imm); break;
814     case 0x9b: ic->f = instr(s8subl_imm); break;
815     case 0x9d: ic->f = instr(cmpult_imm); break;
816     case 0xa0: ic->f = instr(addq_imm); break;
817     case 0xa2: ic->f = instr(s4addq_imm); break;
818     case 0xa9: ic->f = instr(subq_imm); break;
819     case 0xab: ic->f = instr(s4subq_imm); break;
820     case 0xad: ic->f = instr(cmpeq_imm); break;
821     case 0xb2: ic->f = instr(s8addq_imm); break;
822     case 0xbb: ic->f = instr(s8subq_imm); break;
823     case 0xbd: ic->f = instr(cmpule_imm); break;
824     case 0xcd: ic->f = instr(cmplt_imm); break;
825     case 0xed: ic->f = instr(cmple_imm); break;
826    
827     default:fatal("[ Alpha: unimplemented function 0x%03x for"
828     " opcode 0x%02x ]\n", func, opcode);
829     goto bad;
830     }
831     break;
832     case 0x11:
833     if (rc == ALPHA_ZERO) {
834     ic->f = instr(nop);
835     break;
836     }
837     ic->arg[0] = (size_t) &cpu->cd.alpha.r[rc];
838     ic->arg[1] = (size_t) &cpu->cd.alpha.r[ra];
839     if (func & 0x80)
840     ic->arg[2] = (size_t)((rb << 3) + (func >> 8));
841     else
842     ic->arg[2] = (size_t) &cpu->cd.alpha.r[rb];
843     switch (func & 0xff) {
844     case 0x00: ic->f = instr(and); break;
845     case 0x08: ic->f = instr(andnot); break;
846     case 0x14: ic->f = instr(cmovlbs); break;
847     case 0x16: ic->f = instr(cmovlbc); break;
848     case 0x20: ic->f = instr(or);
849     if (ra == ALPHA_ZERO || rb == ALPHA_ZERO) {
850     if (ra == ALPHA_ZERO)
851     ra = rb;
852     ic->f = alpha_mov_r_r[ra + rc*32];
853     }
854     break;
855     case 0x24: ic->f = instr(cmoveq); break;
856     case 0x26: ic->f = instr(cmovne); break;
857     case 0x28: ic->f = instr(ornot); break;
858     case 0x40: ic->f = instr(xor); break;
859     case 0x44: ic->f = instr(cmovlt); break;
860     case 0x46: ic->f = instr(cmovge); break;
861     case 0x48: ic->f = instr(xornot); break;
862     case 0x64: ic->f = instr(cmovle); break;
863     case 0x66: ic->f = instr(cmovgt); break;
864     case 0x80: ic->f = instr(and_imm); break;
865     case 0x88: ic->f = instr(andnot_imm); break;
866     case 0x94: ic->f = instr(cmovlbs_imm); break;
867     case 0x96: ic->f = instr(cmovlbc_imm); break;
868     case 0xa0: ic->f = instr(or_imm); break;
869     case 0xa4: ic->f = instr(cmoveq_imm); break;
870     case 0xa6: ic->f = instr(cmovne_imm); break;
871     case 0xa8: ic->f = instr(ornot_imm); break;
872     case 0xc0: ic->f = instr(xor_imm); break;
873     case 0xc4: ic->f = instr(cmovlt_imm); break;
874     case 0xc6: ic->f = instr(cmovge_imm); break;
875     case 0xc8: ic->f = instr(xornot_imm); break;
876     case 0xe4: ic->f = instr(cmovle_imm); break;
877     case 0xe6: ic->f = instr(cmovgt_imm); break;
878     default:fatal("[ Alpha: unimplemented function 0x%03x for"
879     " opcode 0x%02x ]\n", func, opcode);
880     goto bad;
881     }
882     break;
883     case 0x12:
884     if (rc == ALPHA_ZERO) {
885     ic->f = instr(nop);
886     break;
887     }
888     ic->arg[0] = (size_t) &cpu->cd.alpha.r[rc];
889     ic->arg[1] = (size_t) &cpu->cd.alpha.r[ra];
890     if (func & 0x80)
891     ic->arg[2] = (size_t)((rb << 3) + (func >> 8));
892     else
893     ic->arg[2] = (size_t) &cpu->cd.alpha.r[rb];
894     switch (func & 0xff) {
895     case 0x02: ic->f = instr(mskbl); break;
896     case 0x06: ic->f = instr(extbl); break;
897     case 0x0b: ic->f = instr(insbl); break;
898     case 0x12: ic->f = instr(mskwl); break;
899     case 0x16: ic->f = instr(extwl); break;
900     case 0x1b: ic->f = instr(inswl); break;
901     case 0x22: ic->f = instr(mskll); break;
902     case 0x26: ic->f = instr(extll); break;
903     case 0x2b: ic->f = instr(insll); break;
904     case 0x30: ic->f = instr(zap); break;
905     case 0x31: ic->f = instr(zapnot); break;
906     case 0x32: ic->f = instr(mskql); break;
907     case 0x34: ic->f = instr(srl); break;
908     case 0x36: ic->f = instr(extql); break;
909     case 0x39: ic->f = instr(sll); break;
910     case 0x3b: ic->f = instr(insql); break;
911     case 0x3c: ic->f = instr(sra); break;
912     case 0x52: ic->f = instr(mskwh); break;
913     case 0x57: ic->f = instr(inswh); break;
914     case 0x5a: ic->f = instr(extwh); break;
915     case 0x62: ic->f = instr(msklh); break;
916     case 0x67: ic->f = instr(inslh); break;
917     case 0x6a: ic->f = instr(extlh); break;
918     case 0x72: ic->f = instr(mskqh); break;
919     case 0x77: ic->f = instr(insqh); break;
920     case 0x7a: ic->f = instr(extqh); break;
921     case 0x82: ic->f = instr(mskbl_imm); break;
922     case 0x86: ic->f = instr(extbl_imm); break;
923     case 0x8b: ic->f = instr(insbl_imm); break;
924     case 0x92: ic->f = instr(mskwl_imm); break;
925     case 0x96: ic->f = instr(extwl_imm); break;
926     case 0x9b: ic->f = instr(inswl_imm); break;
927     case 0xa2: ic->f = instr(mskll_imm); break;
928     case 0xa6: ic->f = instr(extll_imm); break;
929     case 0xab: ic->f = instr(insll_imm); break;
930     case 0xb0: ic->f = instr(zap_imm); break;
931     case 0xb1: ic->f = instr(zapnot_imm); break;
932     case 0xb2: ic->f = instr(mskql_imm); break;
933     case 0xb4: ic->f = instr(srl_imm); break;
934     case 0xb6: ic->f = instr(extql_imm); break;
935     case 0xb9: ic->f = instr(sll_imm); break;
936     case 0xbb: ic->f = instr(insql_imm); break;
937     case 0xbc: ic->f = instr(sra_imm); break;
938     case 0xd2: ic->f = instr(mskwh_imm); break;
939     case 0xd7: ic->f = instr(inswh_imm); break;
940     case 0xda: ic->f = instr(extwh_imm); break;
941     case 0xe2: ic->f = instr(msklh_imm); break;
942     case 0xe7: ic->f = instr(inslh_imm); break;
943     case 0xea: ic->f = instr(extlh_imm); break;
944     case 0xf2: ic->f = instr(mskqh_imm); break;
945     case 0xf7: ic->f = instr(insqh_imm); break;
946     case 0xfa: ic->f = instr(extqh_imm); break;
947     default:fatal("[ Alpha: unimplemented function 0x%03x for"
948     " opcode 0x%02x ]\n", func, opcode);
949     goto bad;
950     }
951     break;
952     case 0x13:
953     if (rc == ALPHA_ZERO) {
954     ic->f = instr(nop);
955     break;
956     }
957     ic->arg[0] = (size_t) &cpu->cd.alpha.r[rc];
958     ic->arg[1] = (size_t) &cpu->cd.alpha.r[ra];
959     if (func & 0x80)
960     ic->arg[2] = (size_t)((rb << 3) + (func >> 8));
961     else
962     ic->arg[2] = (size_t) &cpu->cd.alpha.r[rb];
963     switch (func & 0xff) {
964     case 0x00: ic->f = instr(mull); break;
965     case 0x20: ic->f = instr(mulq); break;
966     case 0x30: ic->f = instr(umulh); break;
967     default:fatal("[ Alpha: unimplemented function 0x%03x for"
968     " opcode 0x%02x ]\n", func, opcode);
969     goto bad;
970     }
971     break;
972     case 0x16:
973     if (rc == ALPHA_ZERO) {
974     ic->f = instr(nop);
975     break;
976     }
977     ic->arg[0] = (size_t) &cpu->cd.alpha.f[rc];
978     ic->arg[1] = (size_t) &cpu->cd.alpha.f[ra];
979     ic->arg[2] = (size_t) &cpu->cd.alpha.f[rb];
980     switch (func & 0x7ff) {
981     default:fatal("[ Alpha: unimplemented function 0x%03x for"
982     " opcode 0x%02x ]\n", func, opcode);
983     goto bad;
984     }
985     break;
986     case 0x17:
987     if (rc == ALPHA_ZERO) {
988     ic->f = instr(nop);
989     break;
990     }
991     ic->arg[0] = (size_t) &cpu->cd.alpha.f[rc];
992     ic->arg[1] = (size_t) &cpu->cd.alpha.f[ra];
993     ic->arg[2] = (size_t) &cpu->cd.alpha.f[rb];
994     switch (func & 0x7ff) {
995     case 0x020:
996     /* fclr: */
997     if (ra == 31 && rb == 31)
998     ic->f = instr(clear);
999     else {
1000     /* fabs: */
1001     goto bad;
1002     }
1003     break;
1004     default:fatal("[ Alpha: unimplemented function 0x%03x for"
1005     " opcode 0x%02x ]\n", func, opcode);
1006     goto bad;
1007     }
1008     break;
1009     case 0x18:
1010     switch (iword & 0xffff) {
1011     case 0x4000: /* mb */
1012     case 0x4400: /* wmb */
1013     ic->f = instr(nop);
1014     break;
1015     case 0xc000: /* rdcc ra */
1016     if (ra == ALPHA_ZERO) {
1017     ic->f = instr(nop);
1018     break;
1019     }
1020     ic->arg[0] = (size_t) &cpu->cd.alpha.r[ra];
1021     ic->f = instr(rdcc);
1022     break;
1023     default:fatal("[ Alpha: unimplemented function 0x%03x for"
1024     " opcode 0x%02x ]\n", func, opcode);
1025     goto bad;
1026     }
1027     break;
1028     case 0x1a:
1029     switch ((iword >> 14) & 3) {
1030     case 0: /* JMP */
1031     case 1: /* JSR */
1032     case 2: /* RET */
1033     ic->arg[0] = (size_t) &cpu->cd.alpha.r[ra];
1034     ic->arg[1] = (size_t) &cpu->cd.alpha.r[rb];
1035     if (ra == ALPHA_ZERO) {
1036     if (cpu->machine->show_trace_tree &&
1037     rb == ALPHA_RA)
1038     ic->f = instr(jsr_0_trace);
1039     else
1040     ic->f = instr(jsr_0);
1041     } else {
1042     if (cpu->machine->show_trace_tree)
1043     ic->f = instr(jsr_trace);
1044     else
1045     ic->f = instr(jsr);
1046     }
1047     break;
1048     default:fatal("[ Alpha: unimpl JSR type %i, ra=%i rb=%i ]\n",
1049     ((iword >> 14) & 3), ra, rb);
1050     goto bad;
1051     }
1052     break;
1053     case 0x30: /* BR */
1054     case 0x34: /* BSR */
1055     case 0x38: /* BLBC */
1056     case 0x39: /* BEQ */
1057     case 0x3a: /* BLT */
1058     case 0x3b: /* BLE */
1059     case 0x3c: /* BLBS */
1060     case 0x3d: /* BNE */
1061     case 0x3e: /* BGE */
1062     case 0x3f: /* BGT */
1063     /* To avoid a GCC warning: */
1064     samepage_function = instr(nop);
1065     switch (opcode) {
1066     case 0x30:
1067     case 0x34:
1068     ic->f = instr(br);
1069     samepage_function = instr(br_samepage);
1070     if (ra != ALPHA_ZERO) {
1071     ic->f = instr(br_return);
1072     samepage_function = instr(br_return_samepage);
1073     }
1074     break;
1075     case 0x38:
1076     ic->f = instr(blbc);
1077     samepage_function = instr(blbc_samepage);
1078     break;
1079     case 0x39:
1080     ic->f = instr(beq);
1081     samepage_function = instr(beq_samepage);
1082     break;
1083     case 0x3a:
1084     ic->f = instr(blt);
1085     samepage_function = instr(blt_samepage);
1086     break;
1087     case 0x3b:
1088     ic->f = instr(ble);
1089     samepage_function = instr(ble_samepage);
1090     break;
1091     case 0x3c:
1092     ic->f = instr(blbs);
1093     samepage_function = instr(blbs_samepage);
1094     break;
1095     case 0x3d:
1096     ic->f = instr(bne);
1097     samepage_function = instr(bne_samepage);
1098     break;
1099     case 0x3e:
1100     ic->f = instr(bge);
1101     samepage_function = instr(bge_samepage);
1102     break;
1103     case 0x3f:
1104     ic->f = instr(bgt);
1105     samepage_function = instr(bgt_samepage);
1106     break;
1107     }
1108     ic->arg[1] = (size_t) &cpu->cd.alpha.r[ra];
1109     ic->arg[0] = (iword & 0x001fffff) << 2;
1110     /* Sign-extend: */
1111     if (ic->arg[0] & 0x00400000)
1112     ic->arg[0] |= 0xffffffffff800000ULL;
1113     /* Branches are calculated as PC + 4 + offset. */
1114     ic->arg[0] = (size_t)(ic->arg[0] + 4);
1115     /* Special case: branch within the same page: */
1116     {
1117     uint64_t mask_within_page =
1118     ((ALPHA_IC_ENTRIES_PER_PAGE-1) << 2) | 3;
1119     uint64_t old_pc = addr;
1120     uint64_t new_pc = old_pc + (int32_t)ic->arg[0];
1121     if ((old_pc & ~mask_within_page) ==
1122     (new_pc & ~mask_within_page)) {
1123     ic->f = samepage_function;
1124     ic->arg[0] = (size_t) (
1125     cpu->cd.alpha.cur_ic_page +
1126     ((new_pc & mask_within_page) >> 2));
1127     }
1128     }
1129     break;
1130     default:fatal("[ UNIMPLEMENTED Alpha opcode 0x%x ]\n", opcode);
1131     goto bad;
1132     }
1133    
1134    
1135     #define DYNTRANS_TO_BE_TRANSLATED_TAIL
1136     #include "cpu_dyntrans.c"
1137     #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
1138     }
1139    

  ViewVC Help
Powered by ViewVC 1.1.26