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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12 - (hide annotations)
Mon Oct 8 16:18:38 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 29764 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.905 2005/08/16 09:16:24 debug Exp $
20050628	Continuing the work on the ARM translation engine. end_of_page
		works. Experimenting with load/store translation caches
		(virtual -> physical -> host).
20050629	More ARM stuff (memory access translation cache, mostly). This
		might break a lot of stuff elsewhere, probably some MIPS-
		related translation things.
20050630	Many load/stores are now automatically generated and included
		into cpu_arm_instr.c; 1024 functions in total (!).
		Fixes based on feedback from Alec Voropay: only print 8 hex
		digits instead of 16 in some cases when emulating 32-bit
		machines; similar 8 vs 16 digit fix for breakpoint addresses;
		4Kc has 16 TLB entries, not 48; the MIPS config select1
		register is now printed with "reg ,0".
		Also changing many other occurances of 16 vs 8 digit output.
		Adding cache associativity fields to mips_cpu_types.h; updating
		some other cache fields; making the output of
		mips_cpu_dumpinfo() look nicer.
		Generalizing the bintrans stuff for device accesses to also
		work with the new translation system. (This might also break
		some MIPS things.)
		Adding multi-load/store instructions to the ARM disassembler
		and the translator, and some optimizations of various kinds.
20050701	Adding a simple dev_disk (it can read/write sectors from
		disk images).
20050712	Adding dev_ether (a simple ethernet send/receive device).
		Debugger command "ninstrs" for toggling show_nr_of_instructions
		during runtime.
		Removing the framebuffer logo.
20050713	Continuing on dev_ether.
		Adding a dummy cpu_alpha (again).
20050714	More work on cpu_alpha.
20050715	More work on cpu_alpha. Many instructions work, enough to run
		a simple framebuffer fill test (similar to the ARM test).
20050716	More Alpha stuff.
20050717	Minor updates (Alpha stuff).
20050718	Minor updates (Alpha stuff).
20050719	Generalizing some Alpha instructions.
20050720	More Alpha-related updates.
20050721	Continuing on cpu_alpha. Importing rpb.h from NetBSD/alpha.
20050722	Alpha-related updates: userland stuff (Hello World using
		write() compiled statically for FreeBSD/Alpha runs fine), and
		more instructions are now implemented.
20050723	Fixing ldq_u and stq_u.
		Adding more instructions (conditional moves, masks, extracts,
		shifts).
20050724	More FreeBSD/Alpha userland stuff, and adding some more
		instructions (inserts).
20050725	Continuing on the Alpha stuff. (Adding dummy ldt/stt.)
		Adding a -A command line option to turn off alignment checks
		in some cases (for translated code).
		Trying to remove the old bintrans code which updated the pc
		and nr_of_executed_instructions for every instruction.
20050726	Making another attempt att removing the pc/nr of instructions
		code. This time it worked, huge performance increase for
		artificial test code, but performance loss for real-world
		code :-( so I'm scrapping that code for now.
		Tiny performance increase on Alpha (by using ret instead of
		jmp, to play nice with the Alpha's branch prediction) for the
		old MIPS bintrans backend.
20050727	Various minor fixes and cleanups.
20050728	Switching from a 2-level virtual to host/physical translation
		system for ARM emulation, to a 1-level translation.
		Trying to switch from 2-level to 1-level for the MIPS bintrans
		system as well (Alpha only, so far), but there is at least one
		problem: caches and/or how they work with device mappings.
20050730	Doing the 2-level to 1-level conversion for the i386 backend.
		The cache/device bug is still there for R2K/3K :(
		Various other minor updates (Malta etc).
		The mc146818 clock now updates the UIP bit in a way which works
		better with Linux for at least sgimips and Malta emulation.
		Beginning the work on refactoring the dyntrans system.
20050731	Continuing the dyntrans refactoring.
		Fixing a small but serious host alignment bug in memory_rw.
		Adding support for big-endian load/stores to the i386 bintrans
		backend.
		Another minor i386 bintrans backend update: stores from the
		zero register are now one (or two) loads shorter.
		The slt and sltu instructions were incorrectly implemented for
		the i386 backend; only using them for 32-bit mode for now.
20050801	Continuing the dyntrans refactoring.
		Cleanup of the ns16550 serial controller (removing unnecessary
		code).
		Bugfix (memory corruption bug) in dev_gt, and a patch/hack from
		Alec Voropay for Linux/Malta.
20050802	More cleanup/refactoring of the dyntrans subsystem: adding
		phys_page pointers to the lookup tables, for quick jumps
		between translated pages.
		Better fix for the ns16550 device (but still no real FIFO
		functionality).
		Converting cpu_ppc to the new dyntrans system. This means that
		I will have to start from scratch with implementing each
		instruction, and figure out how to implement dual 64/32-bit
		modes etc.
		Removing the URISC CPU family, because it was useless.
20050803	When selecting a machine type, the main type can now be omitted
		if the subtype name is unique. (I.e. -E can be omitted.)
		Fixing a dyntrans/device update bug. (Writes to offset 0 of
		a device could sometimes go unnoticed.)
		Adding an experimental "instruction combination" hack for
		ARM for memset-like byte fill loops.
20050804	Minor progress on cpu_alpha and related things.
		Finally fixing the MIPS dmult/dmultu bugs.
		Fixing some minor TODOs.
20050805	Generalizing the 8259 PIC. It now also works with Cobalt
		and evbmips emulation, in addition to the x86 hack.
		Finally converting the ns16550 device to use devinit.
		Continuing the work on the dyntrans system. Thinking about
		how to add breakpoints.
20050806	More dyntrans updates. Breakpoints seem to work now.
20050807	Minor updates: cpu_alpha and related things; removing
		dev_malta (as it isn't used any more).
		Dyntrans: working on general "show trace tree" support.
		The trace tree stuff now works with both the old MIPS code and
		with newer dyntrans modes. :)
		Continuing on Alpha-related stuff (trying to get *BSD to boot
		a bit further, adding more instructions, etc).
20050808	Adding a dummy IA64 cpu family, and continuing the refactoring
		of the dyntrans system.
		Removing the regression test stuff, because it was more or
		less useless.
		Adding loadlinked/storeconditional type instructions to the
		Alpha emulation. (Needed for Linux/alpha. Not very well tested
		yet.)
20050809	The function call trace tree now prints a per-function nr of
		arguments. (Semi-meaningless, since that data isn't read yet
		from the ELFs; some hardcoded symbols such as memcpy() and
		strlen() work fine, though.)
		More dyntrans refactoring; taking out more of the things that
		are common to all cpu families.
20050810	Working on adding support for "dual mode" for PPC dyntrans
		(i.e. both 64-bit and 32-bit modes).
		(Re)adding some simple PPC instructions.
20050811	Adding a dummy M68K cpu family. The dyntrans system isn't ready
		for variable-length ISAs yet, so it's completely bogus so far.
		Re-adding more PPC instructions.
		Adding a hack to src/file.c which allows OpenBSD/mac68k a.out
		kernels to be loaded.
		Beginning to add PPC loads/stores. So far they only work in
		32-bit mode.
20050812	The configure file option "add_remote" now accepts symbolic
		host names, in addition to numeric IPv4 addresses.
		Re-adding more PPC instructions.
20050814	Continuing to port back more PPC instructions.
		Found and fixed the cache/device write-update bug for 32-bit
		MIPS bintrans. :-)
		Triggered a really weird and annoying bug in Compaq's C
		compiler; ccc sometimes outputs code which loads from an
		address _before_ checking whether the pointer was NULL or not.
		(I'm not sure how to handle this problem.)
20050815	Removing all of the old x86 instruction execution code; adding
		a new (dummy) dyntrans module for x86.
		Taking the first steps to extend the dyntrans system to support
		variable-length instructions.
		Slowly preparing for the next release.
20050816	Adding a dummy SPARC cpu module.
		Minor updates (documentation etc) for the release.

==============  RELEASE 0.3.5  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26