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

Contents of /trunk/src/cpu_alpha_instr.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12 - (show 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 /*
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