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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12 - (show annotations)
Mon Oct 8 16:18:38 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 38974 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_ppc_instr.c,v 1.28 2005/08/14 23:44:22 debug Exp $
29 *
30 * POWER/PowerPC 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 * invalid: To catch bugs.
49 */
50 X(invalid)
51 {
52 fatal("INTERNAL ERROR\n");
53 exit(1);
54 }
55
56
57 /*
58 * addi: Add immediate.
59 *
60 * arg[0] = pointer to source uint64_t
61 * arg[1] = immediate value (int32_t or larger)
62 * arg[2] = pointer to destination uint64_t
63 */
64 X(addi)
65 {
66 reg(ic->arg[2]) = reg(ic->arg[0]) + (int32_t)ic->arg[1];
67 }
68
69
70 /*
71 * andi_dot: AND immediate, update CR.
72 *
73 * arg[0] = pointer to source uint64_t
74 * arg[1] = immediate value (uint32_t)
75 * arg[2] = pointer to destination uint64_t
76 */
77 X(andi_dot)
78 {
79 MODE_uint_t tmp = reg(ic->arg[0]) & (uint32_t)ic->arg[1];
80 reg(ic->arg[2]) = tmp;
81 update_cr0(cpu, tmp);
82 }
83
84
85 /*
86 * addic: Add immediate, Carry.
87 *
88 * arg[0] = pointer to source uint64_t
89 * arg[1] = immediate value (int32_t or larger)
90 * arg[2] = pointer to destination uint64_t
91 */
92 X(addic)
93 {
94 /* TODO/NOTE: Only for 32-bit mode, so far! */
95 uint64_t tmp = (int32_t)reg(ic->arg[0]);
96 uint64_t tmp2 = tmp;
97
98 tmp2 += (int32_t)ic->arg[1];
99
100 /* NOTE: CA is never cleared, just set. */
101 /* TODO: Is this correct? */
102 if ((tmp2 >> 32) != (tmp >> 32))
103 cpu->cd.ppc.xer |= PPC_XER_CA;
104
105 reg(ic->arg[2]) = (uint32_t)tmp2;
106 }
107
108
109 /*
110 * subfic: Subtract from immediate, Carry.
111 *
112 * arg[0] = pointer to source uint64_t
113 * arg[1] = immediate value (int32_t or larger)
114 * arg[2] = pointer to destination uint64_t
115 */
116 X(subfic)
117 {
118 /* TODO/NOTE: Only for 32-bit mode, so far! */
119 uint64_t tmp = (int32_t)(~reg(ic->arg[0]));
120 uint64_t tmp2 = tmp;
121
122 tmp2 += (int32_t)ic->arg[1] + 1;
123
124 /* NOTE: CA is never cleared, just set. TODO: Is this right? */
125 /* TODO: Is this correct? */
126 if ((tmp2 >> 32) != (tmp >> 32))
127 cpu->cd.ppc.xer |= PPC_XER_CA;
128
129 reg(ic->arg[2]) = (uint32_t)tmp2;
130 }
131
132
133 /*
134 * addic_dot: Add immediate, Carry.
135 *
136 * arg[0] = pointer to source uint64_t
137 * arg[1] = immediate value (int32_t or larger)
138 * arg[2] = pointer to destination uint64_t
139 */
140 X(addic_dot)
141 {
142 /* TODO/NOTE: Only for 32-bit mode, so far! */
143 uint64_t tmp = (uint32_t)reg(ic->arg[0]);
144 uint64_t tmp2 = tmp;
145
146 tmp2 += (int32_t)ic->arg[1];
147
148 /* NOTE: CA is never cleared, just set. */
149 /* TODO: Is this correct? */
150 if ((tmp2 >> 32) != (tmp >> 32))
151 cpu->cd.ppc.xer |= PPC_XER_CA;
152
153 reg(ic->arg[2]) = (uint32_t)tmp2;
154 update_cr0(cpu, tmp2);
155 }
156
157
158 /*
159 * bclr: Branch Conditional to Link Register
160 *
161 * arg[0] = bo
162 * arg[1] = bi
163 * arg[2] = bh
164 */
165 X(bclr)
166 {
167 int bo = ic->arg[0], bi = ic->arg[1] /* , bh = ic->arg[2] */;
168 int ctr_ok, cond_ok;
169 MODE_uint_t tmp, addr = cpu->cd.ppc.lr;
170 if (!(bo & 4))
171 cpu->cd.ppc.ctr --;
172 ctr_ok = (bo >> 2) & 1;
173 tmp = cpu->cd.ppc.ctr;
174 ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );
175 cond_ok = (bo >> 4) & 1;
176 cond_ok |= ( ((bo >> 3) & 1) == ((cpu->cd.ppc.cr >> (31-bi)) & 1) );
177 if (ctr_ok && cond_ok) {
178 if (cpu->machine->show_trace_tree)
179 cpu_functioncall_trace_return(cpu);
180 cpu->pc = addr & ~3;
181 /* Find the new physical page and update pointers: */
182 ppc_pc_to_pointers(cpu);
183 }
184 }
185
186
187 /*
188 * b: Branch (to a different translated page)
189 *
190 * arg[0] = relative offset (as an int32_t)
191 */
192 X(b)
193 {
194 uint64_t low_pc;
195
196 /* Calculate new PC from this instruction + arg[0] */
197 low_pc = ((size_t)ic - (size_t)
198 cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);
199 cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2);
200 cpu->pc += (low_pc << 2);
201 cpu->pc += (int32_t)ic->arg[0];
202
203 /* Find the new physical page and update the translation pointers: */
204 ppc_pc_to_pointers(cpu);
205 }
206
207
208 /*
209 * bc: Branch Conditional (to a different translated page)
210 *
211 * arg[0] = relative offset (as an int32_t)
212 * arg[1] = bo
213 * arg[2] = bi
214 */
215 X(bc)
216 {
217 MODE_uint_t tmp;
218 int ctr_ok, cond_ok, bi = ic->arg[2], bo = ic->arg[1];
219 if (!(bo & 4))
220 cpu->cd.ppc.ctr --;
221 ctr_ok = (bo >> 2) & 1;
222 tmp = cpu->cd.ppc.ctr;
223 ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );
224 cond_ok = (bo >> 4) & 1;
225 cond_ok |= ( ((bo >> 3) & 1) ==
226 ((cpu->cd.ppc.cr >> (31-bi)) & 1) );
227 if (ctr_ok && cond_ok)
228 instr(b)(cpu,ic);
229 }
230
231
232 /*
233 * b_samepage: Branch (to within the same translated page)
234 *
235 * arg[0] = pointer to new ppc_instr_call
236 */
237 X(b_samepage)
238 {
239 cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
240 }
241
242
243 /*
244 * bc_samepage: Branch Conditional (to within the same page)
245 *
246 * arg[0] = new ic ptr
247 * arg[1] = bo
248 * arg[2] = bi
249 */
250 X(bc_samepage)
251 {
252 MODE_uint_t tmp;
253 int ctr_ok, cond_ok, bi = ic->arg[2], bo = ic->arg[1];
254 if (!(bo & 4))
255 cpu->cd.ppc.ctr --;
256 ctr_ok = (bo >> 2) & 1;
257 tmp = cpu->cd.ppc.ctr;
258 ctr_ok |= ( (tmp != 0) ^ ((bo >> 1) & 1) );
259 cond_ok = (bo >> 4) & 1;
260 cond_ok |= ( ((bo >> 3) & 1) ==
261 ((cpu->cd.ppc.cr >> (31-bi)) & 1) );
262 if (ctr_ok && cond_ok)
263 instr(b_samepage)(cpu,ic);
264 }
265
266
267 /*
268 * bl: Branch and Link (to a different translated page)
269 *
270 * arg[0] = relative offset (as an int32_t)
271 */
272 X(bl)
273 {
274 uint32_t low_pc;
275
276 /* Calculate LR: */
277 low_pc = ((size_t)cpu->cd.ppc.next_ic - (size_t)
278 cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);
279 cpu->cd.ppc.lr = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2);
280 cpu->cd.ppc.lr += (low_pc << 2);
281
282 /* Calculate new PC from this instruction + arg[0] */
283 low_pc = ((size_t)ic - (size_t)
284 cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);
285 cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2);
286 cpu->pc += (low_pc << 2);
287 cpu->pc += (int32_t)ic->arg[0];
288
289 /* Find the new physical page and update the translation pointers: */
290 ppc_pc_to_pointers(cpu);
291 }
292
293
294 /*
295 * bl_trace: Branch and Link (to a different translated page) (with trace)
296 *
297 * arg[0] = relative offset (as an int32_t)
298 */
299 X(bl_trace)
300 {
301 uint32_t low_pc;
302
303 /* Calculate LR: */
304 low_pc = ((size_t)cpu->cd.ppc.next_ic - (size_t)
305 cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);
306 cpu->cd.ppc.lr = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2);
307 cpu->cd.ppc.lr += (low_pc << 2);
308
309 /* Calculate new PC from this instruction + arg[0] */
310 low_pc = ((size_t)ic - (size_t)
311 cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);
312 cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2);
313 cpu->pc += (low_pc << 2);
314 cpu->pc += (int32_t)ic->arg[0];
315
316 cpu_functioncall_trace(cpu, cpu->pc);
317
318 /* Find the new physical page and update the translation pointers: */
319 ppc_pc_to_pointers(cpu);
320 }
321
322
323 /*
324 * bl_samepage: Branch and Link (to within the same translated page)
325 *
326 * arg[0] = pointer to new ppc_instr_call
327 */
328 X(bl_samepage)
329 {
330 uint32_t low_pc;
331
332 /* Calculate LR: */
333 low_pc = ((size_t)cpu->cd.ppc.next_ic - (size_t)
334 cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);
335 cpu->cd.ppc.lr = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2);
336 cpu->cd.ppc.lr += (low_pc << 2);
337
338 cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
339 }
340
341
342 /*
343 * bl_samepage_trace: Branch and Link (to within the same translated page)
344 *
345 * arg[0] = pointer to new ppc_instr_call
346 */
347 X(bl_samepage_trace)
348 {
349 uint32_t low_pc;
350
351 /* Calculate LR: */
352 low_pc = ((size_t)cpu->cd.ppc.next_ic - (size_t)
353 cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);
354 cpu->cd.ppc.lr = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2);
355 cpu->cd.ppc.lr += (low_pc << 2);
356
357 cpu->cd.ppc.next_ic = (struct ppc_instr_call *) ic->arg[0];
358
359 /* Calculate new PC (for the trace) */
360 low_pc = ((size_t)cpu->cd.ppc.next_ic - (size_t)
361 cpu->cd.ppc.cur_ic_page) / sizeof(struct ppc_instr_call);
362 cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2);
363 cpu->pc += (low_pc << 2);
364 cpu_functioncall_trace(cpu, cpu->pc);
365 }
366
367
368 /*
369 * cmpd: Compare Doubleword
370 *
371 * arg[0] = ptr to ra
372 * arg[1] = ptr to rb
373 * arg[2] = bf
374 */
375 X(cmpd)
376 {
377 int64_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
378 int bf = ic->arg[2], c;
379 if (tmp < tmp2)
380 c = 8;
381 else if (tmp > tmp2)
382 c = 4;
383 else
384 c = 2;
385 c |= ((cpu->cd.ppc.xer >> 31) & 1); /* SO bit, copied from XER */
386 cpu->cd.ppc.cr &= ~(0xf << (28 - 4*bf));
387 cpu->cd.ppc.cr |= (c << (28 - 4*bf));
388 }
389
390
391 /*
392 * cmpld: Compare Doubleword, unsigned
393 *
394 * arg[0] = ptr to ra
395 * arg[1] = ptr to rb
396 * arg[2] = bf
397 */
398 X(cmpld)
399 {
400 uint64_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
401 int bf = ic->arg[2], c;
402 if (tmp < tmp2)
403 c = 8;
404 else if (tmp > tmp2)
405 c = 4;
406 else
407 c = 2;
408 c |= ((cpu->cd.ppc.xer >> 31) & 1); /* SO bit, copied from XER */
409 cpu->cd.ppc.cr &= ~(0xf << (28 - 4*bf));
410 cpu->cd.ppc.cr |= (c << (28 - 4*bf));
411 }
412
413
414 /*
415 * cmpdi: Compare Doubleword immediate
416 *
417 * arg[0] = ptr to ra
418 * arg[1] = int32_t imm
419 * arg[2] = bf
420 */
421 X(cmpdi)
422 {
423 int64_t tmp = reg(ic->arg[0]), imm = (int32_t)ic->arg[1];
424 int bf = ic->arg[2], c;
425 if (tmp < imm)
426 c = 8;
427 else if (tmp > imm)
428 c = 4;
429 else
430 c = 2;
431 c |= ((cpu->cd.ppc.xer >> 31) & 1); /* SO bit, copied from XER */
432 cpu->cd.ppc.cr &= ~(0xf << (28 - 4*bf));
433 cpu->cd.ppc.cr |= (c << (28 - 4*bf));
434 }
435
436
437 /*
438 * cmpldi: Compare Doubleword immediate, logical
439 *
440 * arg[0] = ptr to ra
441 * arg[1] = int32_t imm
442 * arg[2] = bf
443 */
444 X(cmpldi)
445 {
446 uint64_t tmp = reg(ic->arg[0]), imm = (uint32_t)ic->arg[1];
447 int bf = ic->arg[2], c;
448 if (tmp < imm)
449 c = 8;
450 else if (tmp > imm)
451 c = 4;
452 else
453 c = 2;
454 c |= ((cpu->cd.ppc.xer >> 31) & 1); /* SO bit, copied from XER */
455 cpu->cd.ppc.cr &= ~(0xf << (28 - 4*bf));
456 cpu->cd.ppc.cr |= (c << (28 - 4*bf));
457 }
458
459
460 /*
461 * cmpw: Compare Word
462 *
463 * arg[0] = ptr to ra
464 * arg[1] = ptr to rb
465 * arg[2] = bf
466 */
467 X(cmpw)
468 {
469 int32_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
470 int bf = ic->arg[2], c;
471 if (tmp < tmp2)
472 c = 8;
473 else if (tmp > tmp2)
474 c = 4;
475 else
476 c = 2;
477 c |= ((cpu->cd.ppc.xer >> 31) & 1); /* SO bit, copied from XER */
478 cpu->cd.ppc.cr &= ~(0xf << (28 - 4*bf));
479 cpu->cd.ppc.cr |= (c << (28 - 4*bf));
480 }
481
482
483 /*
484 * cmplw: Compare Word, unsigned
485 *
486 * arg[0] = ptr to ra
487 * arg[1] = ptr to rb
488 * arg[2] = bf
489 */
490 X(cmplw)
491 {
492 uint32_t tmp = reg(ic->arg[0]), tmp2 = reg(ic->arg[1]);
493 int bf = ic->arg[2], c;
494 if (tmp < tmp2)
495 c = 8;
496 else if (tmp > tmp2)
497 c = 4;
498 else
499 c = 2;
500 c |= ((cpu->cd.ppc.xer >> 31) & 1); /* SO bit, copied from XER */
501 cpu->cd.ppc.cr &= ~(0xf << (28 - 4*bf));
502 cpu->cd.ppc.cr |= (c << (28 - 4*bf));
503 }
504
505
506 /*
507 * cmpwi: Compare Word immediate
508 *
509 * arg[0] = ptr to ra
510 * arg[1] = int32_t imm
511 * arg[2] = bf
512 */
513 X(cmpwi)
514 {
515 int32_t tmp = reg(ic->arg[0]), imm = ic->arg[1];
516 int bf = ic->arg[2], c;
517 if (tmp < imm)
518 c = 8;
519 else if (tmp > imm)
520 c = 4;
521 else
522 c = 2;
523 c |= ((cpu->cd.ppc.xer >> 31) & 1); /* SO bit, copied from XER */
524 cpu->cd.ppc.cr &= ~(0xf << (28 - 4*bf));
525 cpu->cd.ppc.cr |= (c << (28 - 4*bf));
526 }
527
528
529 /*
530 * cmplwi: Compare Word immediate, logical
531 *
532 * arg[0] = ptr to ra
533 * arg[1] = int32_t imm
534 * arg[2] = bf
535 */
536 X(cmplwi)
537 {
538 uint32_t tmp = reg(ic->arg[0]), imm = ic->arg[1];
539 int bf = ic->arg[2], c;
540 if (tmp < imm)
541 c = 8;
542 else if (tmp > imm)
543 c = 4;
544 else
545 c = 2;
546 c |= ((cpu->cd.ppc.xer >> 31) & 1); /* SO bit, copied from XER */
547 cpu->cd.ppc.cr &= ~(0xf << (28 - 4*bf));
548 cpu->cd.ppc.cr |= (c << (28 - 4*bf));
549 }
550
551
552 /*
553 * rlwinm:
554 *
555 * arg[0] = ptr to rs
556 * arg[1] = ptr to ra
557 * arg[2] = copy of the instruction word
558 */
559 X(rlwinm)
560 {
561 MODE_uint_t tmp = reg(ic->arg[0]), ra = 0;
562 uint32_t iword = ic->arg[2];
563 int sh, mb, me, rc;
564
565 sh = (iword >> 11) & 31;
566 mb = (iword >> 6) & 31;
567 me = (iword >> 1) & 31;
568 rc = iword & 1;
569
570 /* TODO: Fix this, its performance is awful: */
571 while (sh-- != 0) {
572 int b = (tmp >> 31) & 1;
573 tmp = (tmp << 1) | b;
574 }
575 for (;;) {
576 uint64_t mask;
577 mask = (uint64_t)1 << (31-mb);
578 ra |= (tmp & mask);
579 if (mb == me)
580 break;
581 mb ++;
582 if (mb == 32)
583 mb = 0;
584 }
585
586 reg(ic->arg[1]) = ra;
587 if (rc)
588 update_cr0(cpu, ra);
589 }
590
591
592 /*
593 * srawi:
594 *
595 * arg[0] = ptr to rs
596 * arg[1] = ptr to ra
597 * arg[2] = sh (shift amount)
598 */
599 X(srawi)
600 {
601 uint32_t tmp = reg(ic->arg[0]);
602 int i = 0, j = 0, sh = ic->arg[2];
603
604 cpu->cd.ppc.xer &= ~PPC_XER_CA;
605 if (tmp & 0x80000000)
606 i = 1;
607 while (sh-- > 0) {
608 if (tmp & 1)
609 j ++;
610 tmp >>= 1;
611 if (tmp & 0x40000000)
612 tmp |= 0x80000000;
613 }
614 if (i && j>0)
615 cpu->cd.ppc.xer |= PPC_XER_CA;
616 reg(ic->arg[1]) = (int64_t)(int32_t)tmp;
617 }
618 X(srawi_dot) { instr(srawi)(cpu,ic); update_cr0(cpu, reg(ic->arg[1])); }
619
620
621 /*
622 * crxor: Condition Register XOR
623 *
624 * arg[0] = copy of the instruction word
625 */
626 X(crxor)
627 {
628 uint32_t iword = ic->arg[0];
629 int bt = (iword >> 21) & 31;
630 int ba = (iword >> 16) & 31;
631 int bb = (iword >> 11) & 31;
632 ba = (cpu->cd.ppc.cr >> (31-ba)) & 1;
633 bb = (cpu->cd.ppc.cr >> (31-bb)) & 1;
634 cpu->cd.ppc.cr &= ~(1 << (31-bt));
635 if (ba ^ bb)
636 cpu->cd.ppc.cr |= (1 << (31-bt));
637 }
638
639
640 /*
641 * mflr, etc: Move from Link Register etc.
642 *
643 * arg[0] = pointer to destination register
644 */
645 X(mflr) { reg(ic->arg[0]) = cpu->cd.ppc.lr; }
646 /* TODO: Check privilege level for mfsprg* */
647 X(mfsprg0) { reg(ic->arg[0]) = cpu->cd.ppc.sprg0; }
648 X(mfsprg1) { reg(ic->arg[0]) = cpu->cd.ppc.sprg1; }
649 X(mfsprg2) { reg(ic->arg[0]) = cpu->cd.ppc.sprg2; }
650 X(mfsprg3) { reg(ic->arg[0]) = cpu->cd.ppc.sprg3; }
651
652
653 /*
654 * mtlr etc.: Move to Link Register (or other special register)
655 *
656 * arg[0] = pointer to source register
657 */
658 X(mtlr) { cpu->cd.ppc.lr = reg(ic->arg[0]); }
659 /* TODO: Check privilege level for mtsprg* */
660 X(mtsprg0) { cpu->cd.ppc.sprg0 = reg(ic->arg[0]); }
661 X(mtsprg1) { cpu->cd.ppc.sprg1 = reg(ic->arg[0]); }
662 X(mtsprg2) { cpu->cd.ppc.sprg2 = reg(ic->arg[0]); }
663 X(mtsprg3) { cpu->cd.ppc.sprg3 = reg(ic->arg[0]); }
664
665
666 /*
667 * mfcr: Move From Condition Register
668 *
669 * arg[0] = pointer to destination register
670 */
671 X(mfcr)
672 {
673 reg(ic->arg[0]) = cpu->cd.ppc.cr;
674 }
675
676
677 /*
678 * mfmsr: Move From MSR
679 *
680 * arg[0] = pointer to destination register
681 */
682 X(mfmsr)
683 {
684 reg_access_msr(cpu, (uint64_t*)ic->arg[0], 0);
685 }
686
687
688 /*
689 * mtmsr: Move To MSR
690 *
691 * arg[0] = pointer to source register
692 */
693 X(mtmsr)
694 {
695 reg_access_msr(cpu, (uint64_t*)ic->arg[0], 1);
696 }
697
698
699 /*
700 * mtcrf: Move To Condition Register Fields
701 *
702 * arg[0] = pointer to source register
703 */
704 X(mtcrf)
705 {
706 cpu->cd.ppc.cr &= ~ic->arg[1];
707 cpu->cd.ppc.cr |= (reg(ic->arg[0]) & ic->arg[1]);
708 }
709
710
711 /*
712 * mulli: Multiply Low Immediate.
713 *
714 * arg[0] = pointer to source register ra
715 * arg[1] = int32_t immediate
716 * arg[2] = pointer to destination register rt
717 */
718 X(mulli)
719 {
720 reg(ic->arg[2]) = (uint32_t)(reg(ic->arg[0]) * ic->arg[1]);
721 }
722
723
724 /*
725 * Shifts, and, or, xor, etc.
726 *
727 * arg[0] = pointer to source register rs
728 * arg[1] = pointer to source register rb
729 * arg[2] = pointer to destination register ra
730 */
731 X(slw) { reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0])
732 << (reg(ic->arg[1]) & 63); }
733 X(slw_dot) { reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0])
734 << (reg(ic->arg[1]) & 63);
735 update_cr0(cpu, reg(ic->arg[2])); }
736 X(sraw) { reg(ic->arg[2]) = (int64_t)reg(ic->arg[0])
737 >> (reg(ic->arg[1]) & 63); }
738 X(sraw_dot) { reg(ic->arg[2]) = (int64_t)reg(ic->arg[0])
739 >> (reg(ic->arg[1]) & 63);
740 update_cr0(cpu, reg(ic->arg[2])); }
741 X(and) { reg(ic->arg[2]) = reg(ic->arg[0]) & reg(ic->arg[1]); }
742 X(and_dot) { reg(ic->arg[2]) = reg(ic->arg[0]) & reg(ic->arg[1]);
743 update_cr0(cpu, reg(ic->arg[2])); }
744 X(andc) { reg(ic->arg[2]) = reg(ic->arg[0]) & (~reg(ic->arg[1])); }
745 X(andc_dot) { reg(ic->arg[2]) = reg(ic->arg[0]) & (~reg(ic->arg[1]));
746 update_cr0(cpu, reg(ic->arg[2])); }
747 X(nor) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) | reg(ic->arg[1])); }
748 X(nor_dot) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) | reg(ic->arg[1]));
749 update_cr0(cpu, reg(ic->arg[2])); }
750 X(or) { reg(ic->arg[2]) = reg(ic->arg[0]) | reg(ic->arg[1]); }
751 X(or_dot) { reg(ic->arg[2]) = reg(ic->arg[0]) | reg(ic->arg[1]);
752 update_cr0(cpu, reg(ic->arg[2])); }
753 X(orc) { reg(ic->arg[2]) = reg(ic->arg[0]) | (~reg(ic->arg[1])); }
754 X(orc_dot) { reg(ic->arg[2]) = reg(ic->arg[0]) | (~reg(ic->arg[1]));
755 update_cr0(cpu, reg(ic->arg[2])); }
756 X(xor) { reg(ic->arg[2]) = reg(ic->arg[0]) ^ reg(ic->arg[1]); }
757 X(xor_dot) { reg(ic->arg[2]) = reg(ic->arg[0]) ^ reg(ic->arg[1]);
758 update_cr0(cpu, reg(ic->arg[2])); }
759
760
761 /*
762 * neg:
763 *
764 * arg[0] = pointer to source register ra
765 * arg[1] = pointer to destination register rt
766 */
767 X(neg) { reg(ic->arg[1]) = ~reg(ic->arg[0]) + 1; }
768 X(neg_dot) { reg(ic->arg[1]) = ~reg(ic->arg[0]) + 1;
769 update_cr0(cpu, reg(ic->arg[1])); }
770
771
772 /*
773 * mullw, mulhw[u], divw[u]:
774 *
775 * arg[0] = pointer to source register ra
776 * arg[1] = pointer to source register rb
777 * arg[2] = pointer to destination register rt
778 */
779 X(mullw)
780 {
781 int32_t sum = (int32_t)reg(ic->arg[0]) * (int32_t)reg(ic->arg[1]);
782 reg(ic->arg[2]) = (int32_t)sum;
783 }
784 X(mulhw)
785 {
786 int64_t sum;
787 sum = (int64_t)(int32_t)reg(ic->arg[0])
788 * (int64_t)(int32_t)reg(ic->arg[1]);
789 reg(ic->arg[2]) = sum >> 32;
790 }
791 X(mulhwu)
792 {
793 uint64_t sum;
794 sum = (uint64_t)(uint32_t)reg(ic->arg[0])
795 * (uint64_t)(uint32_t)reg(ic->arg[1]);
796 reg(ic->arg[2]) = sum >> 32;
797 }
798 X(divw)
799 {
800 int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
801 int32_t sum;
802 if (b == 0)
803 sum = 0;
804 else
805 sum = a / b;
806 reg(ic->arg[2]) = (uint32_t)sum;
807 }
808 X(divwu)
809 {
810 uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
811 uint32_t sum;
812 if (b == 0)
813 sum = 0;
814 else
815 sum = a / b;
816 reg(ic->arg[2]) = sum;
817 }
818
819
820 /*
821 * add: Add.
822 *
823 * arg[0] = pointer to source register ra
824 * arg[1] = pointer to source register rb
825 * arg[2] = pointer to destination register rt
826 */
827 X(add)
828 {
829 reg(ic->arg[2]) = reg(ic->arg[0]) + reg(ic->arg[1]);
830 }
831
832
833 /*
834 * addc: Add carrying.
835 *
836 * arg[0] = pointer to source register ra
837 * arg[1] = pointer to source register rb
838 * arg[2] = pointer to destination register rt
839 */
840 X(addc)
841 {
842 /* TODO: this only works in 32-bit mode */
843 uint64_t tmp = (uint32_t)reg(ic->arg[0]);
844 uint64_t tmp2 = tmp;
845 cpu->cd.ppc.xer &= PPC_XER_CA;
846 tmp += (uint32_t)reg(ic->arg[1]);
847 if ((tmp >> 32) == (tmp2 >> 32))
848 cpu->cd.ppc.xer |= PPC_XER_CA;
849 reg(ic->arg[2]) = (uint32_t)tmp;
850 }
851
852
853 /*
854 * adde: Add extended, etc.
855 *
856 * arg[0] = pointer to source register ra
857 * arg[1] = pointer to source register rb
858 * arg[2] = pointer to destination register rt
859 */
860 X(adde)
861 {
862 int old_ca = cpu->cd.ppc.xer & PPC_XER_CA;
863 uint64_t tmp = (uint32_t)reg(ic->arg[0]);
864 uint64_t tmp2 = tmp;
865 cpu->cd.ppc.xer &= PPC_XER_CA;
866 tmp += (uint32_t)reg(ic->arg[1]);
867 if (old_ca)
868 tmp ++;
869 if ((tmp >> 32) == (tmp2 >> 32))
870 cpu->cd.ppc.xer |= PPC_XER_CA;
871
872 reg(ic->arg[2]) = (uint32_t)tmp;
873 }
874 X(addze)
875 {
876 int old_ca = cpu->cd.ppc.xer & PPC_XER_CA;
877 uint64_t tmp = (uint32_t)reg(ic->arg[0]);
878 uint64_t tmp2 = tmp;
879 cpu->cd.ppc.xer &= PPC_XER_CA;
880 if (old_ca)
881 tmp ++;
882 if ((tmp >> 32) == (tmp2 >> 32))
883 cpu->cd.ppc.xer |= PPC_XER_CA;
884 reg(ic->arg[2]) = (uint32_t)tmp;
885 }
886
887
888 /*
889 * subf: Subf, etc.
890 *
891 * arg[0] = pointer to source register ra
892 * arg[1] = pointer to source register rb
893 * arg[2] = pointer to destination register rt
894 */
895 X(subf) { reg(ic->arg[2]) = ~reg(ic->arg[0]) + reg(ic->arg[1]) + 1; }
896 X(subfe)
897 {
898 int old_ca = cpu->cd.ppc.xer & PPC_XER_CA;
899 uint64_t tmp = (uint32_t)(~reg(ic->arg[0]));
900 uint64_t tmp2 = tmp;
901
902 cpu->cd.ppc.xer &= PPC_XER_CA;
903 tmp += (uint32_t)reg(ic->arg[1]);
904 if (old_ca)
905 tmp ++;
906 if ((tmp >> 32) == (tmp2 >> 32))
907 cpu->cd.ppc.xer |= PPC_XER_CA;
908 reg(ic->arg[2]) = (uint32_t)tmp;
909 }
910 X(subfze)
911 {
912 int old_ca = cpu->cd.ppc.xer & PPC_XER_CA;
913 uint64_t tmp = (uint32_t)(~reg(ic->arg[0]));
914 uint64_t tmp2 = tmp;
915 cpu->cd.ppc.xer &= PPC_XER_CA;
916 if (old_ca)
917 tmp ++;
918 if ((tmp >> 32) == (tmp2 >> 32))
919 cpu->cd.ppc.xer |= PPC_XER_CA;
920 reg(ic->arg[2]) = (uint32_t)tmp;
921 }
922
923
924 /*
925 * ori: OR immediate.
926 *
927 * arg[0] = pointer to source uint64_t
928 * arg[1] = immediate value (uint32_t or larger)
929 * arg[2] = pointer to destination uint64_t
930 */
931 X(ori)
932 {
933 reg(ic->arg[2]) = reg(ic->arg[0]) | (uint32_t)ic->arg[1];
934 }
935
936
937 /*
938 * user_syscall: Userland syscall.
939 *
940 * arg[0] = syscall "level" (usually 0)
941 */
942 X(user_syscall)
943 {
944 useremul_syscall(cpu, ic->arg[0]);
945 }
946
947
948 /*
949 * xori: XOR immediate.
950 *
951 * arg[0] = pointer to source uint64_t
952 * arg[1] = immediate value (uint32_t or larger)
953 * arg[2] = pointer to destination uint64_t
954 */
955 X(xori)
956 {
957 reg(ic->arg[2]) = reg(ic->arg[0]) ^ (uint32_t)ic->arg[1];
958 }
959
960
961 #include "tmp_ppc_loadstore.c"
962
963
964 /*****************************************************************************/
965
966
967 X(end_of_page)
968 {
969 /* Update the PC: (offset 0, but on the next page) */
970 cpu->pc &= ~((PPC_IC_ENTRIES_PER_PAGE-1) << 2);
971 cpu->pc += (PPC_IC_ENTRIES_PER_PAGE << 2);
972
973 /* Find the new physical page and update the translation pointers: */
974 ppc_pc_to_pointers(cpu);
975
976 /* end_of_page doesn't count as an executed instruction: */
977 cpu->n_translated_instrs --;
978 }
979
980
981 /*****************************************************************************/
982
983
984 /*
985 * ppc_combine_instructions():
986 *
987 * Combine two or more instructions, if possible, into a single function call.
988 */
989 void COMBINE_INSTRUCTIONS(struct cpu *cpu, struct ppc_instr_call *ic,
990 uint32_t addr)
991 {
992 int n_back;
993 n_back = (addr >> 2) & (PPC_IC_ENTRIES_PER_PAGE-1);
994
995 if (n_back >= 1) {
996 /* TODO */
997 }
998
999 /* TODO: Combine forward as well */
1000 }
1001
1002
1003 /*****************************************************************************/
1004
1005
1006 /*
1007 * ppc_instr_to_be_translated():
1008 *
1009 * Translate an instruction word into an ppc_instr_call. ic is filled in with
1010 * valid data for the translated instruction, or a "nothing" instruction if
1011 * there was a translation failure. The newly translated instruction is then
1012 * executed.
1013 */
1014 X(to_be_translated)
1015 {
1016 uint64_t addr, low_pc, tmp_addr;
1017 uint32_t iword;
1018 unsigned char *page;
1019 unsigned char ib[4];
1020 int main_opcode, rt, rs, ra, rb, rc, aa_bit, l_bit, lk_bit, spr, sh,
1021 xo, imm, load, size, update, zero, bf, bo, bi, bh, oe_bit, n64=0;
1022 void (*samepage_function)(struct cpu *, struct ppc_instr_call *);
1023 void (*rc_f)(struct cpu *, struct ppc_instr_call *);
1024
1025 /* Figure out the (virtual) address of the instruction: */
1026 low_pc = ((size_t)ic - (size_t)cpu->cd.ppc.cur_ic_page)
1027 / sizeof(struct ppc_instr_call);
1028 addr = cpu->pc & ~((PPC_IC_ENTRIES_PER_PAGE-1)
1029 << PPC_INSTR_ALIGNMENT_SHIFT);
1030 addr += (low_pc << PPC_INSTR_ALIGNMENT_SHIFT);
1031 cpu->pc = addr;
1032 addr &= ~0x3;
1033
1034 /* Read the instruction word from memory: */
1035 page = cpu->cd.ppc.host_load[addr >> 12];
1036
1037 if (page != NULL) {
1038 /* fatal("TRANSLATION HIT!\n"); */
1039 memcpy(ib, page + (addr & 0xfff), sizeof(ib));
1040 } else {
1041 /* fatal("TRANSLATION MISS!\n"); */
1042 if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
1043 sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
1044 fatal("to_be_translated(): "
1045 "read failed: TODO\n");
1046 goto bad;
1047 }
1048 }
1049
1050 iword = *((uint32_t *)&ib[0]);
1051
1052 #ifdef HOST_LITTLE_ENDIAN
1053 if (cpu->byte_order == EMUL_BIG_ENDIAN)
1054 #else
1055 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1056 #endif
1057 iword = ((iword & 0xff) << 24) |
1058 ((iword & 0xff00) << 8) |
1059 ((iword & 0xff0000) >> 8) |
1060 ((iword & 0xff000000) >> 24);
1061
1062
1063 #define DYNTRANS_TO_BE_TRANSLATED_HEAD
1064 #include "cpu_dyntrans.c"
1065 #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
1066
1067
1068 /*
1069 * Translate the instruction:
1070 */
1071
1072 main_opcode = iword >> 26;
1073
1074 switch (main_opcode) {
1075
1076 case PPC_HI6_MULLI:
1077 rt = (iword >> 21) & 31;
1078 ra = (iword >> 16) & 31;
1079 imm = (int16_t)(iword & 0xffff);
1080 ic->f = instr(mulli);
1081 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
1082 ic->arg[1] = (ssize_t)imm;
1083 ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
1084 break;
1085
1086 case PPC_HI6_SUBFIC:
1087 rt = (iword >> 21) & 31;
1088 ra = (iword >> 16) & 31;
1089 imm = (int16_t)(iword & 0xffff);
1090 ic->f = instr(subfic);
1091 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
1092 ic->arg[1] = (ssize_t)imm;
1093 ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
1094 break;
1095
1096 case PPC_HI6_CMPLI:
1097 case PPC_HI6_CMPI:
1098 bf = (iword >> 23) & 7;
1099 l_bit = (iword >> 21) & 1;
1100 ra = (iword >> 16) & 31;
1101 if (main_opcode == PPC_HI6_CMPLI) {
1102 imm = iword & 0xffff;
1103 if (l_bit)
1104 ic->f = instr(cmpldi);
1105 else
1106 ic->f = instr(cmplwi);
1107 } else {
1108 imm = (int16_t)(iword & 0xffff);
1109 if (l_bit)
1110 ic->f = instr(cmpdi);
1111 else
1112 ic->f = instr(cmpwi);
1113 }
1114 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
1115 ic->arg[1] = (ssize_t)imm;
1116 ic->arg[2] = bf;
1117 break;
1118
1119 case PPC_HI6_ADDIC:
1120 case PPC_HI6_ADDIC_DOT:
1121 if (cpu->cd.ppc.bits == 64) {
1122 fatal("addic for 64-bit: TODO\n");
1123 goto bad;
1124 }
1125 rt = (iword >> 21) & 31;
1126 ra = (iword >> 16) & 31;
1127 imm = (int16_t)(iword & 0xffff);
1128 if (main_opcode == PPC_HI6_ADDIC)
1129 ic->f = instr(addic);
1130 else
1131 ic->f = instr(addic_dot);
1132 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
1133 ic->arg[1] = (ssize_t)imm;
1134 ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
1135 break;
1136
1137 case PPC_HI6_ADDI:
1138 case PPC_HI6_ADDIS:
1139 rt = (iword >> 21) & 31; ra = (iword >> 16) & 31;
1140 ic->f = instr(addi);
1141 if (ra == 0)
1142 ic->arg[0] = (size_t)(&cpu->cd.ppc.zero);
1143 else
1144 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
1145 ic->arg[1] = (ssize_t)(int16_t)(iword & 0xffff);
1146 if (main_opcode == PPC_HI6_ADDIS)
1147 ic->arg[1] <<= 16;
1148 ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
1149 break;
1150
1151 case PPC_HI6_ANDI_DOT:
1152 case PPC_HI6_ANDIS_DOT:
1153 rs = (iword >> 21) & 31; ra = (iword >> 16) & 31;
1154 ic->f = instr(andi_dot);
1155 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
1156 ic->arg[1] = iword & 0xffff;
1157 if (main_opcode == PPC_HI6_ANDIS_DOT)
1158 ic->arg[1] <<= 16;
1159 ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[ra]);
1160 break;
1161
1162 case PPC_HI6_ORI:
1163 case PPC_HI6_ORIS:
1164 case PPC_HI6_XORI:
1165 case PPC_HI6_XORIS:
1166 rs = (iword >> 21) & 31; ra = (iword >> 16) & 31;
1167 if (main_opcode == PPC_HI6_ORI ||
1168 main_opcode == PPC_HI6_ORIS)
1169 ic->f = instr(ori);
1170 else
1171 ic->f = instr(xori);
1172 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
1173 ic->arg[1] = iword & 0xffff;
1174 if (main_opcode == PPC_HI6_ORIS ||
1175 main_opcode == PPC_HI6_XORIS)
1176 ic->arg[1] <<= 16;
1177 ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[ra]);
1178 break;
1179
1180 case PPC_HI6_LBZ:
1181 case PPC_HI6_LBZU:
1182 case PPC_HI6_LHZ:
1183 case PPC_HI6_LHZU:
1184 case PPC_HI6_LWZ:
1185 case PPC_HI6_LWZU:
1186 case PPC_HI6_STB:
1187 case PPC_HI6_STBU:
1188 case PPC_HI6_STH:
1189 case PPC_HI6_STHU:
1190 case PPC_HI6_STW:
1191 case PPC_HI6_STWU:
1192 rs = (iword >> 21) & 31;
1193 ra = (iword >> 16) & 31;
1194 imm = (int16_t)(iword & 0xffff);
1195 load = 0; zero = 1; size = 0; update = 0;
1196 switch (main_opcode) {
1197 case PPC_HI6_LBZ: load = 1; break;
1198 case PPC_HI6_LBZU: load = 1; update = 1; break;
1199 case PPC_HI6_LHZ: load = 1; size = 1; break;
1200 case PPC_HI6_LHZU: load = 1; size = 1; update = 1; break;
1201 case PPC_HI6_LWZ: load = 1; size = 2; break;
1202 case PPC_HI6_LWZU: load = 1; size = 2; update = 1; break;
1203 case PPC_HI6_STB: break;
1204 case PPC_HI6_STBU: update = 1; break;
1205 case PPC_HI6_STH: size = 1; break;
1206 case PPC_HI6_STHU: size = 1; update = 1; break;
1207 case PPC_HI6_STW: size = 2; break;
1208 case PPC_HI6_STWU: size = 2; update = 1; break;
1209 }
1210 ic->f =
1211 #ifdef MODE32
1212 ppc32_loadstore
1213 #else
1214 ppc_loadstore
1215 #endif
1216 [size + 4*zero + 8*load + (imm==0? 16 : 0) + 32*update];
1217
1218 if (ra == 0 && update) {
1219 fatal("TODO: ra=0 && update?\n");
1220 goto bad;
1221 }
1222 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
1223 if (ra == 0)
1224 ic->arg[1] = (size_t)(&cpu->cd.ppc.zero);
1225 else
1226 ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
1227 ic->arg[2] = (ssize_t)imm;
1228 break;
1229
1230 case PPC_HI6_BC:
1231 aa_bit = (iword >> 1) & 1;
1232 lk_bit = iword & 1;
1233 bo = (iword >> 21) & 31;
1234 bi = (iword >> 16) & 31;
1235 tmp_addr = (int64_t)(int16_t)(iword & 0xfffc);
1236 if (lk_bit) {
1237 fatal("lk_bit: NOT YET\n");
1238 goto bad;
1239 }
1240 if (aa_bit) {
1241 fatal("aa_bit: NOT YET\n");
1242 goto bad;
1243 }
1244 ic->f = instr(bc);
1245 samepage_function = instr(bc_samepage);
1246 ic->arg[0] = (ssize_t)tmp_addr;
1247 ic->arg[1] = bo;
1248 ic->arg[2] = bi;
1249 /* Branches are calculated as cur PC + offset. */
1250 /* Special case: branch within the same page: */
1251 {
1252 uint64_t mask_within_page =
1253 ((PPC_IC_ENTRIES_PER_PAGE-1) << 2) | 3;
1254 uint64_t old_pc = addr;
1255 uint64_t new_pc = old_pc + (int32_t)ic->arg[0];
1256 if ((old_pc & ~mask_within_page) ==
1257 (new_pc & ~mask_within_page)) {
1258 ic->f = samepage_function;
1259 ic->arg[0] = (size_t) (
1260 cpu->cd.ppc.cur_ic_page +
1261 ((new_pc & mask_within_page) >> 2));
1262 }
1263 }
1264 break;
1265
1266 case PPC_HI6_SC:
1267 ic->arg[0] = (iword >> 5) & 0x7f;
1268 if (cpu->machine->userland_emul != NULL)
1269 ic->f = instr(user_syscall);
1270 else {
1271 fatal("PPC non-userland SYSCALL: TODO\n");
1272 goto bad;
1273 }
1274 break;
1275
1276 case PPC_HI6_B:
1277 aa_bit = (iword & 2) >> 1;
1278 lk_bit = iword & 1;
1279 if (aa_bit) {
1280 fatal("aa_bit: NOT YET\n");
1281 goto bad;
1282 }
1283 tmp_addr = (int64_t)(int32_t)((iword & 0x03fffffc) << 6);
1284 tmp_addr = (int64_t)tmp_addr >> 6;
1285 if (lk_bit) {
1286 if (cpu->machine->show_trace_tree) {
1287 ic->f = instr(bl_trace);
1288 samepage_function = instr(bl_samepage_trace);
1289 } else {
1290 ic->f = instr(bl);
1291 samepage_function = instr(bl_samepage);
1292 }
1293 } else {
1294 ic->f = instr(b);
1295 samepage_function = instr(b_samepage);
1296 }
1297 ic->arg[0] = (ssize_t)tmp_addr;
1298 /* Branches are calculated as cur PC + offset. */
1299 /* Special case: branch within the same page: */
1300 {
1301 uint64_t mask_within_page =
1302 ((PPC_IC_ENTRIES_PER_PAGE-1) << 2) | 3;
1303 uint64_t old_pc = addr;
1304 uint64_t new_pc = old_pc + (int32_t)ic->arg[0];
1305 if ((old_pc & ~mask_within_page) ==
1306 (new_pc & ~mask_within_page)) {
1307 ic->f = samepage_function;
1308 ic->arg[0] = (size_t) (
1309 cpu->cd.ppc.cur_ic_page +
1310 ((new_pc & mask_within_page) >> 2));
1311 }
1312 }
1313 break;
1314
1315 case PPC_HI6_19:
1316 xo = (iword >> 1) & 1023;
1317 switch (xo) {
1318
1319 case PPC_19_BCLR:
1320 bo = (iword >> 21) & 31;
1321 bi = (iword >> 16) & 31;
1322 bh = (iword >> 11) & 3;
1323 lk_bit = iword & 1;
1324 if (lk_bit) {
1325 fatal("TODO: bclr with l_bit set\n");
1326 goto bad;
1327 }
1328 ic->f = instr(bclr);
1329 ic->arg[0] = bo;
1330 ic->arg[1] = bi;
1331 ic->arg[2] = bh;
1332 break;
1333
1334 case PPC_19_ISYNC:
1335 /* TODO */
1336 ic->f = instr(nop);
1337 break;
1338
1339 case PPC_19_CRXOR:
1340 ic->f = instr(crxor);
1341 ic->arg[0] = iword;
1342 break;
1343
1344 default:goto bad;
1345 }
1346 break;
1347
1348 case PPC_HI6_RLWINM:
1349 rs = (iword >> 21) & 31;
1350 ra = (iword >> 16) & 31;
1351 ic->f = instr(rlwinm);
1352 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
1353 ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
1354 ic->arg[2] = (uint32_t)iword;
1355 break;
1356
1357 case PPC_HI6_31:
1358 xo = (iword >> 1) & 1023;
1359 switch (xo) {
1360
1361 case PPC_31_CMPL:
1362 case PPC_31_CMP:
1363 bf = (iword >> 23) & 7;
1364 l_bit = (iword >> 21) & 1;
1365 ra = (iword >> 16) & 31;
1366 rb = (iword >> 11) & 31;
1367 if (xo == PPC_31_CMPL) {
1368 if (l_bit)
1369 ic->f = instr(cmpld);
1370 else
1371 ic->f = instr(cmplw);
1372 } else {
1373 if (l_bit)
1374 ic->f = instr(cmpd);
1375 else
1376 ic->f = instr(cmpw);
1377 }
1378 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
1379 ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]);
1380 ic->arg[2] = bf;
1381 break;
1382
1383 case PPC_31_MFSPR:
1384 rt = (iword >> 21) & 31;
1385 spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
1386 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rt]);
1387 switch (spr) {
1388 case 8: ic->f = instr(mflr); break;
1389 case 272: ic->f = instr(mfsprg0); break;
1390 case 273: ic->f = instr(mfsprg1); break;
1391 case 274: ic->f = instr(mfsprg2); break;
1392 case 275: ic->f = instr(mfsprg3); break;
1393 default:fatal("UNIMPLEMENTED spr %i\n", spr);
1394 goto bad;
1395 }
1396 break;
1397
1398 case PPC_31_MTSPR:
1399 rs = (iword >> 21) & 31;
1400 spr = ((iword >> 6) & 0x3e0) + ((iword >> 16) & 31);
1401 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
1402 switch (spr) {
1403 case 8: ic->f = instr(mtlr); break;
1404 case 272: ic->f = instr(mtsprg0); break;
1405 case 273: ic->f = instr(mtsprg1); break;
1406 case 274: ic->f = instr(mtsprg2); break;
1407 case 275: ic->f = instr(mtsprg3); break;
1408 default:fatal("UNIMPLEMENTED spr %i\n", spr);
1409 goto bad;
1410 }
1411 break;
1412
1413 case PPC_31_MFCR:
1414 rt = (iword >> 21) & 31;
1415 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rt]);
1416 ic->f = instr(mfcr);
1417 break;
1418
1419 case PPC_31_MFMSR:
1420 rt = (iword >> 21) & 31;
1421 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rt]);
1422 ic->f = instr(mfmsr);
1423 break;
1424
1425 case PPC_31_MTMSR:
1426 rs = (iword >> 21) & 31;
1427 l_bit = (iword >> 16) & 1;
1428 if (l_bit) {
1429 fatal("TODO: mtmsr l-bit\n");
1430 goto bad;
1431 }
1432 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
1433 ic->f = instr(mtmsr);
1434 break;
1435
1436 case PPC_31_MTCRF:
1437 rs = (iword >> 21) & 31;
1438 {
1439 int i, fxm = (iword >> 12) & 255;
1440 uint32_t tmp = 0;
1441 for (i=0; i<8; i++, fxm <<= 1) {
1442 tmp <<= 4;
1443 if (fxm & 128)
1444 tmp |= 0xf;
1445 }
1446 ic->arg[1] = (uint32_t)tmp;
1447 }
1448 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
1449 ic->f = instr(mtcrf);
1450 break;
1451
1452 case PPC_31_SRAWI:
1453 rs = (iword >> 21) & 31;
1454 ra = (iword >> 16) & 31;
1455 sh = (iword >> 11) & 31;
1456 rc = iword & 1;
1457 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
1458 ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
1459 ic->arg[2] = sh;
1460 if (rc)
1461 ic->f = instr(srawi_dot);
1462 else
1463 ic->f = instr(srawi);
1464 break;
1465
1466 case PPC_31_SYNC:
1467 case PPC_31_EIEIO:
1468 /* TODO */
1469 ic->f = instr(nop);
1470 break;
1471
1472 case PPC_31_NEG:
1473 rt = (iword >> 21) & 31;
1474 ra = (iword >> 16) & 31;
1475 rc = iword & 1;
1476 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
1477 ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rt]);
1478 if (rc)
1479 ic->f = instr(neg_dot);
1480 else
1481 ic->f = instr(neg);
1482 break;
1483
1484 case PPC_31_LBZX:
1485 case PPC_31_LBZUX:
1486 case PPC_31_LHZX:
1487 case PPC_31_LHZUX:
1488 case PPC_31_LWZX:
1489 case PPC_31_LWZUX:
1490 case PPC_31_STBX:
1491 case PPC_31_STBUX:
1492 case PPC_31_STHX:
1493 case PPC_31_STHUX:
1494 case PPC_31_STWX:
1495 case PPC_31_STWUX:
1496 case PPC_31_STDX:
1497 case PPC_31_STDUX:
1498 rs = (iword >> 21) & 31;
1499 ra = (iword >> 16) & 31;
1500 rb = (iword >> 11) & 31;
1501 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
1502 if (ra == 0)
1503 ic->arg[1] = (size_t)(&cpu->cd.ppc.zero);
1504 else
1505 ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[ra]);
1506 ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rb]);
1507 load = 0; zero = 1; size = 0; update = 0;
1508 switch (xo) {
1509 case PPC_31_LBZX: load = 1; break;
1510 case PPC_31_LBZUX: load = update = 1; break;
1511 case PPC_31_LHZX: size = 1; load = 1; break;
1512 case PPC_31_LHZUX: size = 1; load = update = 1; break;
1513 case PPC_31_LWZX: size = 2; load = 1; break;
1514 case PPC_31_LWZUX: size = 2; load = update = 1; break;
1515 case PPC_31_STBX: break;
1516 case PPC_31_STBUX: update = 1; break;
1517 case PPC_31_STHX: size = 1; break;
1518 case PPC_31_STHUX: size = 1; update = 1; break;
1519 case PPC_31_STWX: size = 2; break;
1520 case PPC_31_STWUX: size = 2; update = 1; break;
1521 case PPC_31_STDX: size = 3; break;
1522 case PPC_31_STDUX: size = 3; update = 1; break;
1523 }
1524 ic->f =
1525 #ifdef MODE32
1526 ppc32_loadstore_indexed
1527 #else
1528 ppc_loadstore_indexed
1529 #endif
1530 [size + 4*zero + 8*load + 16*update];
1531 if (ra == 0 && update) {
1532 fatal("TODO: ra=0 && update?\n");
1533 goto bad;
1534 }
1535 break;
1536
1537 case PPC_31_SLW:
1538 case PPC_31_SRAW:
1539 case PPC_31_AND:
1540 case PPC_31_ANDC:
1541 case PPC_31_NOR:
1542 case PPC_31_OR:
1543 case PPC_31_ORC:
1544 case PPC_31_XOR:
1545 rs = (iword >> 21) & 31;
1546 ra = (iword >> 16) & 31;
1547 rb = (iword >> 11) & 31;
1548 rc = iword & 1;
1549 rc_f = NULL;
1550 switch (xo) {
1551 case PPC_31_SLW: ic->f = instr(slw);
1552 rc_f = instr(slw_dot); break;
1553 case PPC_31_SRAW: ic->f = instr(sraw);
1554 rc_f = instr(sraw_dot); break;
1555 case PPC_31_AND: ic->f = instr(and);
1556 rc_f = instr(and_dot); break;
1557 case PPC_31_ANDC: ic->f = instr(andc);
1558 rc_f = instr(andc_dot); break;
1559 case PPC_31_NOR: ic->f = instr(nor);
1560 rc_f = instr(nor_dot); break;
1561 case PPC_31_OR: ic->f = instr(or);
1562 rc_f = instr(or_dot); break;
1563 case PPC_31_ORC: ic->f = instr(orc);
1564 rc_f = instr(orc_dot); break;
1565 case PPC_31_XOR: ic->f = instr(xor);
1566 rc_f = instr(xor_dot); break;
1567 }
1568 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[rs]);
1569 ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]);
1570 ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[ra]);
1571 if (rc)
1572 ic->f = rc_f;
1573 break;
1574
1575 case PPC_31_MULLW:
1576 case PPC_31_MULHW:
1577 case PPC_31_MULHWU:
1578 case PPC_31_DIVW:
1579 case PPC_31_DIVWU:
1580 case PPC_31_ADD:
1581 case PPC_31_ADDC:
1582 case PPC_31_ADDE:
1583 case PPC_31_ADDZE:
1584 case PPC_31_SUBF:
1585 case PPC_31_SUBFE:
1586 case PPC_31_SUBFZE:
1587 rt = (iword >> 21) & 31;
1588 ra = (iword >> 16) & 31;
1589 rb = (iword >> 11) & 31;
1590 oe_bit = (iword >> 10) & 1;
1591 rc = iword & 1;
1592 if (rc) {
1593 fatal("RC bit not yet implemented\n");
1594 goto bad;
1595 }
1596 if (oe_bit) {
1597 fatal("oe_bit not yet implemented\n");
1598 goto bad;
1599 }
1600 switch (xo) {
1601 case PPC_31_MULLW: ic->f = instr(mullw); break;
1602 case PPC_31_MULHW: ic->f = instr(mulhw); break;
1603 case PPC_31_MULHWU: ic->f = instr(mulhwu); break;
1604 case PPC_31_DIVW: ic->f = instr(divw); n64=1; break;
1605 case PPC_31_DIVWU: ic->f = instr(divwu); n64=1; break;
1606 case PPC_31_ADD: ic->f = instr(add); break;
1607 case PPC_31_ADDC: ic->f = instr(addc); n64=1; break;
1608 case PPC_31_ADDE: ic->f = instr(adde); n64=1; break;
1609 case PPC_31_ADDZE: ic->f = instr(addze); n64=1; break;
1610 case PPC_31_SUBF: ic->f = instr(subf); break;
1611 case PPC_31_SUBFE: ic->f = instr(subfe); n64=1; break;
1612 case PPC_31_SUBFZE: ic->f = instr(subfze); n64=1;break;
1613 }
1614 ic->arg[0] = (size_t)(&cpu->cd.ppc.gpr[ra]);
1615 ic->arg[1] = (size_t)(&cpu->cd.ppc.gpr[rb]);
1616 ic->arg[2] = (size_t)(&cpu->cd.ppc.gpr[rt]);
1617 if (cpu->cd.ppc.bits == 64 && n64) {
1618 fatal("Not yet for 64-bit mode\n");
1619 goto bad;
1620 }
1621 break;
1622
1623 default:goto bad;
1624 }
1625 break;
1626
1627 default:goto bad;
1628 }
1629
1630
1631 #define DYNTRANS_TO_BE_TRANSLATED_TAIL
1632 #include "cpu_dyntrans.c"
1633 #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
1634 }
1635

  ViewVC Help
Powered by ViewVC 1.1.26