1#
2#   This file is part of the program psim.
3#
4#   Copyright 1994, 1995, 1996, 1997, 2003, 2004 Andrew Cagney
5#
6#   --
7#
8#   The pseudo-code that appears below, translated into C, was copied
9#   by Andrew Cagney of Moss Vale, Australia.
10#
11#   This pseudo-code is copied by permission from the publication
12#   "The PowerPC Architecture: A Specification for A New Family of
13#   RISC Processors" (ISBN 1-55860-316-6) copyright 1993, 1994 by
14#   International Business Machines Corporation.
15#
16#   THIS PERMISSION IS PROVIDED WITHOUT WARRANTY OF ANY KIND, EITHER
17#   EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES
18#   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19#
20#   --
21#
22#   This program is free software; you can redistribute it and/or modify
23#   it under the terms of the GNU General Public License as published by
24#   the Free Software Foundation; either version 3 of the License, or
25#   (at your option) any later version.
26#
27#   This program is distributed in the hope that it will be useful,
28#   but WITHOUT ANY WARRANTY; without even the implied warranty of
29#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
30#   GNU General Public License for more details.
31#
32#   You should have received a copy of the GNU General Public License
33#   along with this program; if not, see <http://www.gnu.org/licenses/>.
34#
35
36:cache::::RA:RA:
37:cache:::signed_word *:rA:RA:(cpu_registers(processor)->gpr + RA)
38:cache:::unsigned32:RA_BITMASK:RA:(1 << RA)
39:compute:::int:RA_is_0:RA:(RA == 0)
40:cache::::RT:RT:
41:cache:::signed_word *:rT:RT:(cpu_registers(processor)->gpr + RT)
42:cache:::unsigned32:RT_BITMASK:RT:(1 << RT)
43:cache::::RS:RS:
44:cache:::signed_word *:rS:RS:(cpu_registers(processor)->gpr + RS)
45:cache:::unsigned32:RS_BITMASK:RS:(1 << RS)
46:cache::::RB:RB:
47:cache:::signed_word *:rB:RB:(cpu_registers(processor)->gpr + RB)
48:cache:::unsigned32:RB_BITMASK:RB:(1 << RB)
49:scratch::::FRA:FRA:
50:cache:::unsigned64 *:frA:FRA:(cpu_registers(processor)->fpr + FRA)
51:cache:::unsigned32:FRA_BITMASK:FRA:(1 << FRA)
52:scratch::::FRB:FRB:
53:cache:::unsigned64 *:frB:FRB:(cpu_registers(processor)->fpr + FRB)
54:cache:::unsigned32:FRB_BITMASK:FRB:(1 << FRB)
55:scratch::::FRC:FRC:
56:cache:::unsigned64 *:frC:FRC:(cpu_registers(processor)->fpr + FRC)
57:cache:::unsigned32:FRC_BITMASK:FRC:(1 << FRC)
58:scratch::::FRS:FRS:
59:cache:::unsigned64 *:frS:FRS:(cpu_registers(processor)->fpr + FRS)
60:cache:::unsigned32:FRS_BITMASK:FRS:(1 << FRS)
61:scratch::::FRT:FRT:
62:cache:::unsigned64 *:frT:FRT:(cpu_registers(processor)->fpr + FRT)
63:cache:::unsigned32:FRT_BITMASK:FRT:(1 << FRT)
64:cache:::unsigned_word:EXTS_SI:SI:((signed_word)(signed16)instruction)
65:scratch::::BI:BI:
66:cache::::BIT32_BI:BI:BIT32(BI)
67:cache::::BF:BF:
68:cache:::unsigned32:BF_BITMASK:BF:(1 << BF)
69:scratch::::BA:BA:
70:cache::::BIT32_BA:BA:BIT32(BA)
71:cache:::unsigned32:BA_BITMASK:BA:(1 << BA)
72:scratch::::BB:BB:
73:cache::::BIT32_BB:BB:BIT32(BB)
74:cache:::unsigned32:BB_BITMASK:BB:(1 << BB)
75:cache::::BT:BT:
76:cache:::unsigned32:BT_BITMASK:BT:(1 << BT)
77:cache:::unsigned_word:EXTS_BD_0b00:BD:(((signed_word)(signed16)instruction) & ~3)
78:cache:::unsigned_word:EXTS_LI_0b00:LI:((((signed_word)(signed32)(instruction << 6)) >> 6) & ~0x3)
79:cache:::unsigned_word:EXTS_D:D:((signed_word)(signed16)(instruction))
80:cache:::unsigned_word:EXTS_DS_0b00:DS:(((signed_word)(signed16)instruction) & ~0x3)
81#:compute:::int:SPR_is_256:SPR:(SPR == 256)
82
83# PowerPC models
84::model:604:ppc604:  PPC_UNIT_BAD,   PPC_UNIT_BAD,   1,  1,  0
85::model:603e:ppc603e:PPC_UNIT_BAD,   PPC_UNIT_BAD,   1,  1,  0
86::model:603:ppc603:  PPC_UNIT_BAD,   PPC_UNIT_BAD,   1,  1,  0
87::model:601:ppc601:  PPC_UNIT_BAD,   PPC_UNIT_BAD,   1,  1,  0
88
89# Flags for model.h
90::model-macro:::
91	#define PPC_INSN_INT(OUT_MASK, IN_MASK, RC) \
92		do { \
93		  if (CURRENT_MODEL_ISSUE > 0) { \
94		    if (RC) \
95		      ppc_insn_int_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, 1 << 0); \
96		    else \
97		      ppc_insn_int(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK); \
98		  } \
99		} while (0)
100
101	#define PPC_INSN_INT_CR(OUT_MASK, IN_MASK, CR_MASK) \
102		do { \
103		  if (CURRENT_MODEL_ISSUE > 0) \
104		    ppc_insn_int_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, CR_MASK); \
105		} while (0)
106
107	#define PPC_INSN_CR(OUT_MASK, IN_MASK) \
108		do { \
109		  if (CURRENT_MODEL_ISSUE > 0) \
110		    ppc_insn_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK); \
111		} while (0)
112
113	#define PPC_INSN_FLOAT(OUT_MASK, IN_MASK, RC) \
114		do { \
115		  if (CURRENT_MODEL_ISSUE > 0) { \
116		    if (RC) \
117		      ppc_insn_float(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK); \
118		    else \
119		      ppc_insn_float_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, 1 << 0); \
120		  } \
121		} while (0)
122
123	#define PPC_INSN_FLOAT_CR(OUT_MASK, IN_MASK, CR_MASK) \
124		do { \
125		  if (CURRENT_MODEL_ISSUE > 0) \
126		    ppc_insn_float_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, CR_MASK); \
127		} while (0)
128
129	#define PPC_INSN_INT_FLOAT(OUT_INT_MASK, OUT_FP_MASK, IN_INT_MASK, IN_FP_MASK) \
130		do { \
131		  if (CURRENT_MODEL_ISSUE > 0) \
132		    ppc_insn_int_float(MY_INDEX, cpu_model(processor), OUT_INT_MASK, OUT_FP_MASK, IN_INT_MASK, IN_FP_MASK); \
133		} while (0)
134
135	#define PPC_INSN_FROM_SPR(INT_MASK, SPR) \
136		do { \
137		  if (CURRENT_MODEL_ISSUE > 0) \
138		    ppc_insn_from_spr(MY_INDEX, cpu_model(processor), INT_MASK, SPR); \
139		} while (0)
140
141	#define PPC_INSN_TO_SPR(INT_MASK, SPR) \
142		do { \
143		  if (CURRENT_MODEL_ISSUE > 0) \
144		    ppc_insn_to_spr(MY_INDEX, cpu_model(processor), INT_MASK, SPR); \
145		} while (0)
146
147	#define PPC_INSN_MFCR(INT_MASK) \
148		do { \
149		  if (CURRENT_MODEL_ISSUE > 0) \
150		    ppc_insn_mfcr(MY_INDEX, cpu_model(processor), INT_MASK); \
151		} while (0)
152
153	#define PPC_INSN_MTCR(INT_MASK, FXM) \
154		do { \
155		  if (CURRENT_MODEL_ISSUE > 0) \
156		    ppc_insn_mtcr(MY_INDEX, cpu_model(processor), INT_MASK, FXM); \
157		} while (0)
158
159::model-data:::
160	typedef enum _ppc_function_unit {
161	  PPC_UNIT_BAD,				/* unknown function unit */
162	  PPC_UNIT_IU,				/* integer unit (601/603 style) */
163	  PPC_UNIT_SRU,				/* system register unit (601/603 style) */
164	  PPC_UNIT_SCIU1,			/* 1st single cycle integer unit (604 style) */
165	  PPC_UNIT_SCIU2,			/* 2nd single cycle integer unit (604 style) */
166	  PPC_UNIT_MCIU,			/* multiple cycle integer unit (604 style) */
167	  PPC_UNIT_FPU,				/* floating point unit */
168	  PPC_UNIT_LSU,				/* load/store unit */
169	  PPC_UNIT_BPU,				/* branch unit */
170	  nr_ppc_function_units
171	} ppc_function_unit;
172
173	/* Structure to hold timing information on a per instruction basis */
174	struct _model_time {
175	  ppc_function_unit first_unit;			/* first functional unit this insn could use */
176	  ppc_function_unit second_unit;		/* second functional unit this insn could use */
177	  signed16	    issue;			/* # cycles before function unit can process other insns */
178	  signed16	    done;			/* # cycles before insn is done */
179	  unsigned32	    flags;			/* any flags that are needed */
180	};
181
182	/* Register mappings in status masks */
183	#define PPC_CR_REG	0			/* start of CR0 .. CR7 */
184	#define PPC_FPSCR_REG	(PPC_CR_REG + 8)	/* start of fpscr register */
185
186	#define PPC_NO_SPR	(-1)			/* flag for no SPR register */
187
188	/* Return if 1 bit set */
189	#define PPC_ONE_BIT_SET_P(x) (((x) & ((x)-1)) == 0)
190
191	/* Structure for each functional unit that is busy */
192	typedef struct _model_busy model_busy;
193	struct _model_busy {
194	  model_busy *next;				/* next function unit */
195	  ppc_function_unit unit;			/* function unit name */
196	  unsigned32 int_busy;				/* int registers that are busy */
197	  unsigned32 fp_busy;				/* floating point registers that are busy */
198	  unsigned32 cr_fpscr_busy;			/* CR/FPSCR registers that are busy */
199	  signed16 spr_busy;				/* SPR register that is busy or PPC_NO_SPR */
200	  unsigned32 vr_busy;				/* AltiVec registers that are busy */
201	  signed16 vscr_busy;				/* AltiVec status register busy */
202	  signed16 issue;				/* # of cycles until unit can accept another insn */
203	  signed16 done;				/* # of cycles until insn is done */
204	  signed16 nr_writebacks;			/* # of registers this unit writes back */
205	};
206
207	/* Structure to hold the current state information for the simulated CPU model */
208	struct _model_data {
209	  cpu *processor;				/* point back to processor */
210	  const char *name;				/* model name */
211	  const model_time *timing;			/* timing information */
212	  model_busy busy_head;				/* dummy entry to head list of busy function units */
213	  model_busy *busy_tail;			/* tail of list of busy function units */
214	  model_busy *free_list;			/* list of model_busy structs not in use */
215	  count_type nr_cycles;				/* # cycles */
216	  count_type nr_branches;			/* # branches */
217	  count_type nr_branches_fallthrough;		/* # conditional branches that fell through */
218	  count_type nr_branch_predict_trues;		/* # branches predicted correctly */
219	  count_type nr_branch_predict_falses;		/* # branches predicted incorrectly */
220	  count_type nr_branch_conditional[32];		/* # of each type of bc */
221	  count_type nr_mtcrf_crs[9];			/* # of CR's moved in a mtcrf instruction */
222	  count_type nr_stalls_data;			/* # of stalls for data */
223	  count_type nr_stalls_unit;			/* # of stalls waiting for a function unit */
224	  count_type nr_stalls_serialize;		/* # of stalls waiting for things to quiet down */
225	  count_type nr_stalls_writeback;		/* # of stalls waiting for a writeback slot */
226	  count_type nr_units[nr_ppc_function_units];	/* function unit counts */
227	  int max_nr_writebacks;			/* max # of writeback slots available */
228	  unsigned32 int_busy;				/* int registers that are busy */
229	  unsigned32 fp_busy;				/* floating point registers that are busy */
230	  unsigned32 cr_fpscr_busy;			/* CR/FPSCR registers that are busy */
231	  unsigned8 spr_busy[nr_of_sprs];		/* SPR registers that are busy */
232	  unsigned32 vr_busy;				/* AltiVec registers that are busy */
233	  unsigned8 vscr_busy;				/* AltiVec SC register busy */
234	  unsigned8 busy[nr_ppc_function_units];	/* whether a function is busy or not */
235	};
236
237	static const char *const ppc_function_unit_name[ (int)nr_ppc_function_units ] = {
238	  "unknown functional unit instruction",
239	  "integer functional unit instruction",
240	  "system register functional unit instruction",
241	  "1st single cycle integer functional unit instruction",
242	  "2nd single cycle integer functional unit instruction",
243	  "multiple cycle integer functional unit instruction",
244	  "floating point functional unit instruction",
245	  "load/store functional unit instruction",
246	  "branch functional unit instruction",
247	};
248
249	static const char *const ppc_branch_conditional_name[32] = {
250	  "branch if --CTR != 0 and condition is FALSE",				/* 0000y */
251	  "branch if --CTR != 0 and condition is FALSE, reverse branch likely",
252	  "branch if --CTR == 0 and condition is FALSE",				/* 0001y */
253	  "branch if --CTR == 0 and condition is FALSE, reverse branch likely",
254	  "branch if the condition is FALSE",						/* 001zy */
255	  "branch if the condition is FALSE, reverse branch likely",
256	  "branch if the condition is FALSE (ignored bit 1 set to 1)",			/* 001zy */
257	  "branch if the condition is FALSE, reverse branch likely (ignored bit 4 set to 1)",
258	  "branch if --CTR != 0 and condition is TRUE",					/* 0100y */
259	  "branch if --CTR != 0 and condition is TRUE, reverse branch likely",
260	  "branch if --CTR == 0 and condition is TRUE",					/* 0101y */
261	  "branch if --CTR == 0 and condition is TRUE, reverse branch likely",
262	  "branch if the condition is TRUE",						/* 011zy */
263	  "branch if the condition is TRUE, reverse branch likely",
264	  "branch if the condition is TRUE (ignored bit 1 set to 1)",			/* 011zy */
265	  "branch if the condition is TRUE, reverse branch likely (ignored bit 4 set to 1)",
266	  "branch if --CTR != 0",							/* 1z00y */
267	  "branch if --CTR != 0, reverse branch likely",
268	  "branch if --CTR == 0",							/* 1z01y */
269	  "branch if --CTR == 0, reverse branch likely",
270	  "branch always",								/* 1z1zz */
271	  "branch always (ignored bit 5 set to 1)",
272	  "branch always (ignored bit 4 set to 1)",					/* 1z1zz */
273	  "branch always (ignored bits 4,5 set to 1)",
274	  "branch if --CTR != 0 (ignored bit 1 set to 1)",				/* 1z00y */
275	  "branch if --CTR != 0, reverse branch likely (ignored bit 1 set to 1)",
276	  "branch if --CTR == 0 (ignored bit 1 set to 1)",				/* 1z01y */
277	  "branch if --CTR == 0, reverse branch likely (ignored bit 1 set to 1)",
278	  "branch always (ignored bit 1 set to 1)",					/* 1z1zz */
279	  "branch always (ignored bits 1,5 set to 1)",
280	  "branch always (ignored bits 1,4 set to 1)",					/* 1z1zz */
281	  "branch always (ignored bits 1,4,5 set to 1)",
282	};
283
284	static const char *const ppc_nr_mtcrf_crs[9] = {
285	  "mtcrf moving 0 CRs",
286	  "mtcrf moving 1 CR",
287	  "mtcrf moving 2 CRs",
288	  "mtcrf moving 3 CRs",
289	  "mtcrf moving 4 CRs",
290	  "mtcrf moving 5 CRs",
291	  "mtcrf moving 6 CRs",
292	  "mtcrf moving 7 CRs",
293	  "mtcrf moving all CRs",
294	};
295
296# Trace releasing resources
297void::model-static::model_trace_release:model_data *model_ptr, model_busy *busy
298	int i;
299	TRACE(trace_model,("done, %s, %d writeback%s\n", ppc_function_unit_name[busy->unit],
300			   busy->nr_writebacks, busy->nr_writebacks == 1 ? "" : "s"));
301	if (busy->int_busy) {
302	  for(i = 0; i < 32; i++) {
303	    if (((1 << i) & busy->int_busy) != 0) {
304	      TRACE(trace_model, ("Register r%d is now available.\n", i));
305	    }
306	  }
307	}
308	if (busy->fp_busy) {
309	  for(i = 0; i < 32; i++) {
310	    if (((1 << i) & busy->fp_busy) != 0) {
311	      TRACE(trace_model, ("Register f%d is now available.\n", i));
312	    }
313	  }
314	}
315	if (busy->cr_fpscr_busy) {
316	  for(i = 0; i < 8; i++) {
317	    if (((1 << i) & busy->cr_fpscr_busy) != 0) {
318	      TRACE(trace_model, ("Register cr%d is now available.\n", i));
319	    }
320	  }
321	  if (busy->cr_fpscr_busy & 0x100)
322	    TRACE(trace_model, ("Register fpscr is now available.\n"));
323	}
324	if (busy->spr_busy != PPC_NO_SPR)
325	  TRACE(trace_model, ("Register %s is now available.\n", spr_name(busy->spr_busy)));
326	if (busy->vr_busy) {
327	  for(i = 0; i < 32; i++) {
328	    if (((1 << i) & busy->vr_busy) != 0) {
329	      TRACE(trace_model, ("Register v%d is now available.\n", i));
330	    }
331	  }
332	}
333	if (busy->vscr_busy)
334	  TRACE(trace_model, ("VSCR Register is now available.\n", spr_name(busy->spr_busy)));
335
336# Trace making registers busy
337void::model-static::model_trace_make_busy:model_data *model_ptr, unsigned32 int_mask, unsigned32 fp_mask, unsigned32 cr_mask
338	int i;
339	if (int_mask) {
340	  for(i = 0; i < 32; i++) {
341	    if (((1 << i) & int_mask) != 0) {
342	      TRACE(trace_model, ("Register r%d is now busy.\n", i));
343	    }
344	  }
345	}
346	if (fp_mask) {
347	  for(i = 0; i < 32; i++) {
348	    if (((1 << i) & fp_mask) != 0) {
349	      TRACE(trace_model, ("Register f%d is now busy.\n", i));
350	    }
351	  }
352	}
353	if (cr_mask) {
354	  for(i = 0; i < 8; i++) {
355	    if (((1 << i) & cr_mask) != 0) {
356	      TRACE(trace_model, ("Register cr%d is now busy.\n", i));
357	    }
358	  }
359	}
360
361# Trace waiting for registers to become available
362void::model-static::model_trace_busy_p:model_data *model_ptr, unsigned32 int_busy, unsigned32 fp_busy, unsigned32 cr_or_fpscr_busy, int spr_busy
363	int i;
364	if (int_busy) {
365	  int_busy &= model_ptr->int_busy;
366	  for(i = 0; i < 32; i++) {
367	    if (((1 << i) & int_busy) != 0) {
368	      TRACE(trace_model, ("Waiting for register r%d.\n", i));
369	    }
370	  }
371	}
372	if (fp_busy) {
373	  fp_busy &= model_ptr->fp_busy;
374	  for(i = 0; i < 32; i++) {
375	    if (((1 << i) & fp_busy) != 0) {
376	      TRACE(trace_model, ("Waiting for register f%d.\n", i));
377	    }
378	  }
379	}
380	if (cr_or_fpscr_busy) {
381	  cr_or_fpscr_busy &= model_ptr->cr_fpscr_busy;
382	  for(i = 0; i < 8; i++) {
383	    if (((1 << i) & cr_or_fpscr_busy) != 0) {
384	      TRACE(trace_model, ("Waiting for register cr%d.\n", i));
385	    }
386	  }
387	  if (cr_or_fpscr_busy & 0x100)
388	    TRACE(trace_model, ("Waiting for register fpscr.\n"));
389	}
390	if (spr_busy != PPC_NO_SPR && model_ptr->spr_busy[spr_busy])
391	  TRACE(trace_model, ("Waiting for register %s.\n", spr_name(spr_busy)));
392
393# Advance state to next cycle, releasing any registers allocated
394void::model-internal::model_new_cycle:model_data *model_ptr
395	model_busy *cur_busy  = model_ptr->busy_head.next;
396	model_busy *free_list = model_ptr->free_list;
397	model_busy *busy_tail = &model_ptr->busy_head;
398	int nr_writebacks     = model_ptr->max_nr_writebacks;
399	model_busy *next;
400
401	model_ptr->nr_cycles++;
402	TRACE(trace_model,("New cycle %lu\n", (unsigned long)model_ptr->nr_cycles));
403	for ( ; cur_busy; cur_busy = next) {
404	  next = cur_busy->next;
405	  if (--cur_busy->done <= 0) {		/* function unit done, release registers if we have writeback slots */
406	    nr_writebacks -= cur_busy->nr_writebacks;
407	    if (nr_writebacks >= 0) {
408	      model_ptr->int_busy &= ~cur_busy->int_busy;
409	      model_ptr->fp_busy &= ~cur_busy->fp_busy;
410	      model_ptr->cr_fpscr_busy &= ~cur_busy->cr_fpscr_busy;
411	      if (cur_busy->spr_busy != PPC_NO_SPR)
412		model_ptr->spr_busy[cur_busy->spr_busy] = 0;
413	      model_ptr->vr_busy &= ~cur_busy->vr_busy;
414	      model_ptr->vscr_busy = ~cur_busy->vscr_busy;
415
416	      if (WITH_TRACE && ppc_trace[trace_model])
417		model_trace_release(model_ptr, cur_busy);
418
419	      model_ptr->busy[cur_busy->unit] = 0;
420	      cur_busy->next = free_list;
421	      free_list = cur_busy;
422	    }
423	    else {	/* writeback slots not available */
424	      TRACE(trace_model,("%d writeback slot%s not available for %s\n",
425				 cur_busy->nr_writebacks,
426				 cur_busy->nr_writebacks == 1 ? " is" : "s are",
427				 ppc_function_unit_name[cur_busy->unit]));
428	      cur_busy->done++;			/* undo -- above */
429	      model_ptr->nr_stalls_writeback++;
430	      busy_tail->next = cur_busy;
431	      busy_tail = cur_busy;
432	    }
433	  }
434	  else if (--cur_busy->issue <= 0) {	/* function unit pipelined, allow new use */
435	    TRACE(trace_model,("pipeline, %s ready for next client\n", ppc_function_unit_name[cur_busy->unit]));
436	    model_ptr->busy[cur_busy->unit] = 0;
437	    busy_tail->next = cur_busy;
438	    busy_tail = cur_busy;
439	  }
440	  else {
441	    TRACE(trace_model,("%s still working, issue = %d, done = %d\n",
442			       ppc_function_unit_name[cur_busy->unit],
443			       cur_busy->issue,
444			       cur_busy->done));
445	    busy_tail->next = cur_busy;
446	    busy_tail = cur_busy;
447	  }
448	}
449
450	busy_tail->next = (model_busy *)0;
451	model_ptr->busy_tail = busy_tail;
452	model_ptr->free_list = free_list;
453
454# Mark a function unit as busy, return the busy structure
455model_busy *::model-internal::model_make_busy:model_data *model_ptr, ppc_function_unit unit, int issue, int done
456	model_busy *busy;
457
458	TRACE(trace_model,("unit = %s, issue = %d, done = %d\n", ppc_function_unit_name[unit], issue, done));
459
460	if (!model_ptr->free_list) {
461	  busy = ZALLOC(model_busy);
462	}
463	else {
464	  busy = model_ptr->free_list;
465	  model_ptr->free_list = busy->next;
466	  busy->next = (model_busy *)0;
467	  busy->int_busy = 0;
468	  busy->fp_busy = 0;
469	  busy->cr_fpscr_busy = 0;
470	  busy->nr_writebacks = 0;
471	  busy->vr_busy = 0;
472	  busy->vscr_busy = 0;
473	}
474
475	busy->unit = unit;
476	busy->issue = issue;
477	busy->done = done;
478	busy->spr_busy = PPC_NO_SPR;
479	model_ptr->busy_tail->next = busy;
480	model_ptr->busy_tail = busy;
481	model_ptr->busy[unit] = 1;
482	model_ptr->nr_units[unit]++;
483	return busy;
484
485# Wait until a function unit is non-busy, and then allocate a busy pointer & return the pointer
486model_busy *::model-internal::model_wait_for_unit:itable_index index, model_data *const model_ptr, const model_time *const time_ptr
487	ppc_function_unit first_unit = time_ptr->first_unit;
488	ppc_function_unit second_unit = time_ptr->second_unit;
489	int stall_increment = 0;
490
491	for (;;) {
492	  if (!model_ptr->busy[first_unit])
493	    return model_make_busy(model_ptr, first_unit,
494				   model_ptr->timing[index].issue,
495				   model_ptr->timing[index].done);
496
497	  if (!model_ptr->busy[second_unit])
498	    return model_make_busy(model_ptr, second_unit,
499				   model_ptr->timing[index].issue,
500				   model_ptr->timing[index].done);
501
502	  TRACE(trace_model,("all function units are busy for %s\n", itable[index].name));
503	  model_ptr->nr_stalls_unit += stall_increment;		/* don't count first stall */
504	  stall_increment = 1;
505	  model_new_cycle(model_ptr);
506	}
507
508# Serialize the processor, waiting for all instructions to drain out before adding an instruction.
509void::model-function::model_serialize:itable_index index, model_data *model_ptr
510	while (model_ptr->busy_head.next) {
511	  TRACE(trace_model,("waiting for pipeline to empty\n"));
512	  model_ptr->nr_stalls_serialize++;
513	  model_new_cycle(model_ptr);
514	}
515	(void) model_make_busy(model_ptr,
516			       model_ptr->timing[index].first_unit,
517			       model_ptr->timing[index].issue,
518			       model_ptr->timing[index].done);
519
520# Wait for a CR to become unbusy
521void::model-function::model_wait_for_cr:model_data *model_ptr, unsigned CRBIT
522	unsigned u;
523	unsigned32 cr_mask;
524	int cr_var = 0;
525	for (u = 0xc0000000; (u != 0) && (CRBIT & u) == 0; u >>= 4 )
526	  cr_var++;
527
528	cr_mask = (1 << cr_var);
529	while ((model_ptr->cr_fpscr_busy & cr_mask) != 0) {
530	  TRACE(trace_model,("waiting for CR %d\n", cr_var));
531	  model_ptr->nr_stalls_data++;
532	  model_new_cycle(model_ptr);
533	}
534
535# Schedule an instruction that takes integer input registers and produces output registers
536void::model-function::ppc_insn_int:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask
537	const unsigned32 int_mask = out_mask | in_mask;
538	model_busy *busy_ptr;
539
540	if ((model_ptr->int_busy & int_mask) != 0) {
541	  model_new_cycle(model_ptr);			/* don't count first dependency as a stall */
542
543	  while ((model_ptr->int_busy & int_mask) != 0) {
544	    if (WITH_TRACE && ppc_trace[trace_model])
545	      model_trace_busy_p(model_ptr, int_mask, 0, 0, PPC_NO_SPR);
546
547	    model_ptr->nr_stalls_data++;
548	    model_new_cycle(model_ptr);
549	  }
550	}
551
552	busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
553	model_ptr->int_busy |= out_mask;
554	busy_ptr->int_busy |= out_mask;
555	if (out_mask)
556	  busy_ptr->nr_writebacks = (PPC_ONE_BIT_SET_P(out_mask)) ? 1 : 2;
557
558	if (WITH_TRACE && ppc_trace[trace_model])
559	  model_trace_make_busy(model_ptr, out_mask, 0, 0);
560
561# Schedule an instruction that takes integer input registers and produces output registers & sets a CR register
562void::model-function::ppc_insn_int_cr:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask, const unsigned32 cr_mask
563	const unsigned32 int_mask = out_mask | in_mask;
564	model_busy *busy_ptr;
565
566	if ((model_ptr->int_busy & int_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
567	  model_new_cycle(model_ptr);			/* don't count first dependency as a stall */
568
569	  while ((model_ptr->int_busy & int_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
570	    if (WITH_TRACE && ppc_trace[trace_model])
571	      model_trace_busy_p(model_ptr, int_mask, 0, cr_mask, PPC_NO_SPR);
572
573	    model_ptr->nr_stalls_data++;
574	    model_new_cycle(model_ptr);
575	  }
576	}
577
578	busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
579	model_ptr->int_busy |= out_mask;
580	busy_ptr->int_busy |= out_mask;
581	model_ptr->cr_fpscr_busy |= cr_mask;
582	busy_ptr->cr_fpscr_busy |= cr_mask;
583	if (out_mask)
584	  busy_ptr->nr_writebacks = (PPC_ONE_BIT_SET_P(out_mask)) ? 1 : 2;
585
586	if (cr_mask)
587	  busy_ptr->nr_writebacks++;
588
589	if (WITH_TRACE && ppc_trace[trace_model])
590	  model_trace_make_busy(model_ptr, out_mask, 0, cr_mask);
591
592
593# Schedule an instruction that takes CR input registers and produces output CR registers
594void::model-function::ppc_insn_cr:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask
595	const unsigned32 cr_mask = out_mask | in_mask;
596	model_busy *busy_ptr;
597
598	if ((model_ptr->cr_fpscr_busy & cr_mask) != 0) {
599	  model_new_cycle(model_ptr);			/* don't count first dependency as a stall */
600
601	  while ((model_ptr->cr_fpscr_busy & cr_mask) != 0) {
602	    if (WITH_TRACE && ppc_trace[trace_model])
603	      model_trace_busy_p(model_ptr, 0, 0, cr_mask, PPC_NO_SPR);
604
605	    model_ptr->nr_stalls_data++;
606	    model_new_cycle(model_ptr);
607	  }
608	}
609
610	busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
611	model_ptr->cr_fpscr_busy |= out_mask;
612	busy_ptr->cr_fpscr_busy |= out_mask;
613	if (out_mask)
614	  busy_ptr->nr_writebacks = 1;
615
616	if (WITH_TRACE && ppc_trace[trace_model])
617	  model_trace_make_busy(model_ptr, 0, 0, out_mask);
618
619
620# Schedule an instruction that takes floating point input registers and produces an output fp register
621void::model-function::ppc_insn_float:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask
622	const unsigned32 fp_mask = out_mask | in_mask;
623	model_busy *busy_ptr;
624
625	if ((model_ptr->fp_busy & fp_mask) != 0) {
626	  model_new_cycle(model_ptr);			/* don't count first dependency as a stall */
627
628	  while ((model_ptr->fp_busy & fp_mask) != 0) {
629	    if (WITH_TRACE && ppc_trace[trace_model])
630	      model_trace_busy_p(model_ptr, 0, fp_mask, 0, PPC_NO_SPR);
631
632	    model_ptr->nr_stalls_data++;
633	    model_new_cycle(model_ptr);
634	  }
635	}
636
637	busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
638	model_ptr->fp_busy |= out_mask;
639	busy_ptr->fp_busy |= out_mask;
640	busy_ptr->nr_writebacks = 1;
641	if (WITH_TRACE && ppc_trace[trace_model])
642	  model_trace_make_busy(model_ptr, 0, out_mask, 0);
643
644
645# Schedule an instruction that takes floating point input registers and produces an output fp register & sets a CR reg
646void::model-function::ppc_insn_float_cr:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask, const unsigned32 cr_mask
647	const unsigned32 fp_mask = out_mask | in_mask;
648	model_busy *busy_ptr;
649
650	if ((model_ptr->fp_busy & fp_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
651	  model_new_cycle(model_ptr);			/* don't count first dependency as a stall */
652
653	  while ((model_ptr->fp_busy & fp_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
654	    if (WITH_TRACE && ppc_trace[trace_model])
655	      model_trace_busy_p(model_ptr, 0, fp_mask, cr_mask, PPC_NO_SPR);
656
657	    model_ptr->nr_stalls_data++;
658	    model_new_cycle(model_ptr);
659	  }
660	}
661
662	busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
663	model_ptr->fp_busy |= out_mask;
664	busy_ptr->fp_busy |= out_mask;
665	model_ptr->cr_fpscr_busy |= cr_mask;
666	busy_ptr->cr_fpscr_busy |= cr_mask;
667	busy_ptr->nr_writebacks = (cr_mask) ? 2 : 1;
668	if (WITH_TRACE && ppc_trace[trace_model])
669	  model_trace_make_busy(model_ptr, 0, out_mask, cr_mask);
670
671
672# Schedule an instruction that takes both int/float input registers and produces output int/float registers
673void::model-function::ppc_insn_int_float:itable_index index, model_data *model_ptr, const unsigned32 out_int_mask, const unsigned32 out_fp_mask, const unsigned32 in_int_mask, const unsigned32 in_fp_mask
674	const unsigned32 int_mask = out_int_mask | in_int_mask;
675	const unsigned32 fp_mask = out_fp_mask | in_fp_mask;
676	model_busy *busy_ptr;
677
678	if ((model_ptr->int_busy & int_mask) || (model_ptr->fp_busy & fp_mask)) {
679	  model_new_cycle(model_ptr);			/* don't count first dependency as a stall */
680
681	  while ((model_ptr->int_busy & int_mask) || (model_ptr->fp_busy & fp_mask)) {
682	    if (WITH_TRACE && ppc_trace[trace_model])
683	      model_trace_busy_p(model_ptr, int_mask, fp_mask, 0, PPC_NO_SPR);
684
685	    model_ptr->nr_stalls_data++;
686	    model_new_cycle(model_ptr);
687	  }
688
689	  busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
690	  model_ptr->int_busy |= out_int_mask;
691	  busy_ptr->int_busy |= out_int_mask;
692	  model_ptr->fp_busy |= out_fp_mask;
693	  busy_ptr->fp_busy |= out_fp_mask;
694	  busy_ptr->nr_writebacks = ((out_int_mask) ? 1 : 0) + ((out_fp_mask) ? 1 : 0);
695	  if (WITH_TRACE && ppc_trace[trace_model])
696	    model_trace_make_busy(model_ptr, out_int_mask, out_fp_mask, 0);
697	  return;
698	}
699
700# Schedule an MFSPR instruction that takes 1 special purpose register and produces an integer output register
701void::model-function::ppc_insn_from_spr:itable_index index, model_data *model_ptr, const unsigned32 int_mask, const unsigned nSPR
702	model_busy *busy_ptr;
703
704	while ((model_ptr->int_busy & int_mask) != 0 || model_ptr->spr_busy[nSPR] != 0) {
705	  if (WITH_TRACE && ppc_trace[trace_model])
706	    model_trace_busy_p(model_ptr, int_mask, 0, 0, nSPR);
707
708	  model_ptr->nr_stalls_data++;
709	  model_new_cycle(model_ptr);
710	}
711
712	busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
713	model_ptr->int_busy |= int_mask;
714	busy_ptr->int_busy |= int_mask;
715	busy_ptr->nr_writebacks = 1;
716	if (WITH_TRACE && ppc_trace[trace_model])
717	  model_trace_make_busy(model_ptr, int_mask, 0, 0);
718
719# Schedule an MTSPR instruction that takes 1 integer register and produces a special purpose output register
720void::model-function::ppc_insn_to_spr:itable_index index, model_data *model_ptr, const unsigned32 int_mask, const unsigned nSPR
721	model_busy *busy_ptr;
722
723	while ((model_ptr->int_busy & int_mask) != 0 || model_ptr->spr_busy[nSPR] != 0) {
724	  if (WITH_TRACE && ppc_trace[trace_model])
725	    model_trace_busy_p(model_ptr, int_mask, 0, 0, nSPR);
726
727	  model_ptr->nr_stalls_data++;
728	  model_new_cycle(model_ptr);
729	}
730
731	busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
732	busy_ptr->spr_busy = nSPR;
733	model_ptr->spr_busy[nSPR] = 1;
734	busy_ptr->nr_writebacks = 1;
735	TRACE(trace_model,("Making register %s busy.\n", spr_name(nSPR)));
736
737# Schedule a MFCR instruction that moves the CR into an integer regsiter
738void::model-function::ppc_insn_mfcr:itable_index index, model_data *model_ptr, unsigned32 int_mask
739	const unsigned32 cr_mask = 0xff;
740	model_busy *busy_ptr;
741
742	while (((model_ptr->int_busy & int_mask) | (model_ptr->cr_fpscr_busy & cr_mask)) != 0) {
743	  if (WITH_TRACE && ppc_trace[trace_model])
744	    model_trace_busy_p(model_ptr, int_mask, 0, cr_mask, PPC_NO_SPR);
745
746	  model_ptr->nr_stalls_data++;
747	  model_new_cycle(model_ptr);
748	}
749
750	busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
751	model_ptr->int_busy |= int_mask;
752	busy_ptr->int_busy |= int_mask;
753	busy_ptr->nr_writebacks = 1;
754	if (WITH_TRACE && ppc_trace[trace_model])
755	  model_trace_make_busy(model_ptr, int_mask, 0, 0);
756
757# Schedule a MTCR instruction that moves an integer register into the CR
758void::model-function::ppc_insn_mtcr:itable_index index, model_data *model_ptr, unsigned32 int_mask, unsigned FXM
759	int f;
760	int nr_crs = 0;
761	unsigned32 cr_mask = 0;
762	const model_time *normal_time = &model_ptr->timing[index];
763	static const model_time ppc604_1bit_time = { PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0 };
764	model_busy *busy_ptr;
765
766	for (f = 0; f < 8; f++) {
767	  if (FXM & (0x80 >> f)) {
768	    cr_mask |= (1 << f);
769	    nr_crs++;
770	  }
771	}
772
773	while (((model_ptr->int_busy & int_mask) | (model_ptr->cr_fpscr_busy & cr_mask)) != 0) {
774	  if (WITH_TRACE && ppc_trace[trace_model])
775	    model_trace_busy_p(model_ptr, int_mask, 0, cr_mask, PPC_NO_SPR);
776
777	  model_ptr->nr_stalls_data++;
778	  model_new_cycle(model_ptr);
779	}
780
781	/* If only one CR is being moved, use the SCIU, not the MCIU on the 604 */
782	if (CURRENT_MODEL == MODEL_ppc604 && nr_crs == 1) {
783	  normal_time = &ppc604_1bit_time;
784	}
785
786	busy_ptr = model_wait_for_unit(index, model_ptr, normal_time);
787	busy_ptr->cr_fpscr_busy |= cr_mask;
788	model_ptr->cr_fpscr_busy |= cr_mask;
789	model_ptr->nr_mtcrf_crs[nr_crs]++;
790	busy_ptr->nr_writebacks = 1;
791	if (WITH_TRACE && ppc_trace[trace_model])
792	  model_trace_make_busy(model_ptr, 0, 0, cr_mask);
793
794model_data *::model-function::model_create:cpu *processor
795	model_data *model_ptr = ZALLOC(model_data);
796	model_ptr->name = model_name[CURRENT_MODEL];
797	model_ptr->timing = model_time_mapping[CURRENT_MODEL];
798	model_ptr->processor = processor;
799	model_ptr->nr_cycles = 1;
800	model_ptr->busy_tail = &model_ptr->busy_head;
801	switch (CURRENT_MODEL) {
802	case MODEL_ppc601:  model_ptr->max_nr_writebacks = 1; break;	/* ??? */
803	case MODEL_ppc603:  model_ptr->max_nr_writebacks = 2; break;
804	case MODEL_ppc603e: model_ptr->max_nr_writebacks = 2; break;
805	case MODEL_ppc604:  model_ptr->max_nr_writebacks = 2; break;
806	default: error ("Unknown model %d\n", CURRENT_MODEL);
807	}
808	return model_ptr;
809
810void::model-function::model_init:model_data *model_ptr
811
812void::model-function::model_halt:model_data *model_ptr
813	/* Let pipeline drain */
814	while (model_ptr->busy_head.next)
815	  model_new_cycle(model_ptr);
816
817unsigned_word::model-function::model_get_number_of_stalls:model_data *model_ptr
818	return (model_ptr->nr_stalls_data
819	        + model_ptr->nr_stalls_unit
820	        + model_ptr->nr_stalls_serialize
821	        + model_ptr->nr_stalls_writeback);
822
823unsigned_word::model-function::model_get_number_of_cycles:model_data *model_ptr
824	return (model_ptr->nr_cycles);
825
826model_print *::model-function::model_mon_info:model_data *model_ptr
827	model_print *head;
828	model_print *tail;
829	ppc_function_unit i;
830	count_type nr_insns;
831	int j;
832
833	head = tail = ZALLOC(model_print);
834	tail->count = model_ptr->nr_cycles;
835	tail->name = "cycle";
836	tail->suffix_plural = "s";
837	tail->suffix_singular = "";
838
839	if (model_ptr->nr_stalls_data) {
840	  tail->next = ZALLOC(model_print);
841	  tail = tail->next;
842	  tail->count = model_ptr->nr_stalls_data;
843	  tail->name = "stall";
844	  tail->suffix_plural = "s waiting for data";
845	  tail->suffix_singular = " waiting for data";
846	}
847
848	if (model_ptr->nr_stalls_unit) {
849	  tail->next = ZALLOC(model_print);
850	  tail = tail->next;
851	  tail->count = model_ptr->nr_stalls_unit;
852	  tail->name = "stall";
853	  tail->suffix_plural = "s waiting for a function unit";
854	  tail->suffix_singular = " waiting for a function unit";
855	}
856
857	if (model_ptr->nr_stalls_serialize) {
858	  tail->next = ZALLOC(model_print);
859	  tail = tail->next;
860	  tail->count = model_ptr->nr_stalls_serialize;
861	  tail->name = "stall";
862	  tail->suffix_plural = "s waiting for serialization";
863	  tail->suffix_singular = " waiting for serialization";
864	}
865
866	if (model_ptr->nr_stalls_writeback) {
867	  tail->next = ZALLOC(model_print);
868	  tail = tail->next;
869	  tail->count = model_ptr->nr_stalls_writeback;
870	  tail->name = "";
871	  tail->suffix_plural = "times a write-back slot was unavailable";
872	  tail->suffix_singular = "time a writeback was unavailable";
873	}
874
875	if (model_ptr->nr_branches) {
876	  tail->next = ZALLOC(model_print);
877	  tail = tail->next;
878	  tail->count = model_ptr->nr_branches;
879	  tail->name = "branch";
880	  tail->suffix_plural = "es";
881	  tail->suffix_singular = "";
882	}
883
884	if (model_ptr->nr_branches_fallthrough) {
885	  tail->next = ZALLOC(model_print);
886	  tail = tail->next;
887	  tail->count = model_ptr->nr_branches_fallthrough;
888	  tail->name = "conditional branch";
889	  tail->suffix_plural = "es fell through";
890	  tail->suffix_singular = " fell through";
891	}
892
893	if (model_ptr->nr_branch_predict_trues) {
894	  tail->next = ZALLOC(model_print);
895	  tail = tail->next;
896	  tail->count = model_ptr->nr_branch_predict_trues;
897	  tail->name = "successful branch prediction";
898	  tail->suffix_plural = "s";
899	  tail->suffix_singular = "";
900	}
901
902	if (model_ptr->nr_branch_predict_falses) {
903	  tail->next = ZALLOC(model_print);
904	  tail = tail->next;
905	  tail->count = model_ptr->nr_branch_predict_falses;
906	  tail->name = "unsuccessful branch prediction";
907	  tail->suffix_plural = "s";
908	  tail->suffix_singular = "";
909	}
910
911	for (j = 0; j < (sizeof(ppc_branch_conditional_name) / sizeof(ppc_branch_conditional_name[0])) ; j++) {
912	  if (model_ptr->nr_branch_conditional[j]) {
913	    tail->next = ZALLOC(model_print);
914	    tail = tail->next;
915	    tail->count = model_ptr->nr_branch_conditional[j];
916	    tail->name = ppc_branch_conditional_name[j];
917	    tail->suffix_plural = " conditional branches";
918	    tail->suffix_singular = " conditional branch";
919	  }
920	}
921
922	for (j = 0; j < 9; j++) {
923	  if (model_ptr->nr_mtcrf_crs[j]) {
924	    tail->next = ZALLOC(model_print);
925	    tail = tail->next;
926	    tail->count = model_ptr->nr_mtcrf_crs[j];
927	    tail->name = ppc_nr_mtcrf_crs[j];
928	    tail->suffix_plural = " instructions";
929	    tail->suffix_singular = " instruction";
930	  }
931	}
932
933	nr_insns = 0;
934	for (i = PPC_UNIT_BAD; i < nr_ppc_function_units; i++) {
935	  if (model_ptr->nr_units[i]) {
936	    nr_insns += model_ptr->nr_units[i];
937	    tail->next = ZALLOC(model_print);
938	    tail = tail->next;
939	    tail->count = model_ptr->nr_units[i];
940	    tail->name = ppc_function_unit_name[i];
941	    tail->suffix_plural = "s";
942	    tail->suffix_singular = "";
943	  }
944	}
945
946	tail->next = ZALLOC(model_print);
947	tail = tail->next;
948	tail->count = nr_insns;
949	tail->name = "instruction";
950	tail->suffix_plural = "s that were accounted for in timing info";
951	tail->suffix_singular = " that was accounted for in timing info";
952
953	tail->next = (model_print *)0;
954	return head;
955
956void::model-function::model_mon_info_free:model_data *model_ptr, model_print *ptr
957	while (ptr) {
958	  model_print *next = ptr->next;
959	  free((void *)ptr);
960	  ptr = next;
961	}
962
963void::model-function::model_branches:model_data *model_ptr, int failed, int conditional
964	model_ptr->nr_units[PPC_UNIT_BPU]++;
965	if (failed)
966	  model_ptr->nr_branches_fallthrough++;
967	else
968	  model_ptr->nr_branches++;
969	if (conditional >= 0)
970	  model_ptr->nr_branch_conditional[conditional]++;
971	model_new_cycle(model_ptr);	/* A branch always ends the current cycle */
972
973void::model-function::model_branch_predict:model_data *model_ptr, int success
974	if (success)
975	  model_ptr->nr_branch_predict_trues++;
976	else
977	  model_ptr->nr_branch_predict_falses++;
978
979
980# The following (illegal) instruction is `known' by gen and is
981# called when ever an illegal instruction is encountered
982::internal::illegal
983	program_interrupt(processor, cia,
984	                  illegal_instruction_program_interrupt);
985
986
987# The following (floating point unavailable) instruction is `known' by gen
988# and is called when ever an a floating point instruction is to be
989# executed but floating point is make unavailable by the MSR
990::internal::floating_point_unavailable
991	floating_point_unavailable_interrupt(processor, cia);
992
993
994#
995# Floating point support functions
996#
997
998# Convert 32bit single to 64bit double
999unsigned64::function::DOUBLE:unsigned32 WORD
1000	unsigned64 FRT;
1001	if (EXTRACTED32(WORD, 1, 8) > 0
1002	    && EXTRACTED32(WORD, 1, 8) < 255) {
1003	  /* normalized operand */
1004	  int not_word_1_1 = !EXTRACTED32(WORD, 1, 1); /*2.6.3 bug*/
1005	  FRT = (INSERTED64(EXTRACTED32(WORD, 0, 1), 0, 1)
1006	         | INSERTED64(not_word_1_1, 2, 2)
1007	         | INSERTED64(not_word_1_1, 3, 3)
1008	         | INSERTED64(not_word_1_1, 4, 4)
1009	         | INSERTED64(EXTRACTED32(WORD, 2, 31), 5, (63 - 29)));
1010	}
1011	else if (EXTRACTED32(WORD, 1, 8) == 0
1012	         && EXTRACTED32(WORD, 9, 31) != 0) {
1013	  /* denormalized operand */
1014	  int sign = EXTRACTED32(WORD, 0, 0);
1015	  int exp = -126;
1016	  unsigned64 frac = INSERTED64(EXTRACTED32(WORD, 9, 31), 1, (52 - 29));
1017	  /* normalize the operand */
1018	  while (MASKED64(frac, 0, 0) == 0) {
1019	    frac <<= 1;
1020	    exp -= 1;
1021	  }
1022	  FRT = (INSERTED64(sign, 0, 0)
1023	         | INSERTED64(exp + 1023, 1, 11)
1024	         | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
1025	}
1026	else if (EXTRACTED32(WORD, 1, 8) == 255
1027		 || EXTRACTED32(WORD, 1, 31) == 0) {
1028	  FRT = (INSERTED64(EXTRACTED32(WORD, 0, 1), 0, 1)
1029	         | INSERTED64(EXTRACTED32(WORD, 1, 1), 2, 2)
1030	         | INSERTED64(EXTRACTED32(WORD, 1, 1), 3, 3)
1031	         | INSERTED64(EXTRACTED32(WORD, 1, 1), 4, 4)
1032	         | INSERTED64(EXTRACTED32(WORD, 2, 31), 5, (63 - 29)));
1033	}
1034	else {
1035	  error("DOUBLE - unknown case\n");
1036	  FRT = 0;
1037	}
1038	return FRT;
1039
1040# Convert 64bit single to 32bit double
1041unsigned32::function::SINGLE:unsigned64 FRS
1042	unsigned32 WORD;
1043	if (EXTRACTED64(FRS, 1, 11) > 896
1044	    || EXTRACTED64(FRS, 1, 63) == 0) {
1045	  /* no denormalization required (includes Zero/Infinity/NaN) */
1046	  WORD = (INSERTED32(EXTRACTED64(FRS, 0, 1), 0, 1)
1047	          | INSERTED32(EXTRACTED64(FRS, 5, 34), 2, 31));
1048	}
1049	else if (874 <= EXTRACTED64(FRS, 1, 11)
1050	         && EXTRACTED64(FRS, 1, 11) <= 896) {
1051	  /* denormalization required */
1052	  int sign = EXTRACTED64(FRS, 0, 0);
1053	  int exp = EXTRACTED64(FRS, 1, 11) - 1023;
1054	  unsigned64 frac = (BIT64(0)
1055	                     | INSERTED64(EXTRACTED64(FRS, 12, 63), 1, 52));
1056	  /* denormalize the operand */
1057	  while (exp < -126) {
1058	    frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63);
1059	    exp += 1;
1060	  }
1061	  WORD = (INSERTED32(sign, 0, 0)
1062	          | INSERTED32(0x00, 1, 8)
1063	          | INSERTED32(EXTRACTED64(frac, 1, 23), 9, 31));
1064	}
1065	else {
1066	  WORD = 0x0; /* ??? */
1067	}
1068	return WORD;
1069
1070
1071# round 64bit double to 64bit but single
1072void::function::Round_Single:cpu *processor, int sign, int *exp, unsigned64 *frac_grx
1073	/* comparisons ignore u bits */
1074	unsigned64 out;
1075	int inc = 0;
1076	int lsb = EXTRACTED64(*frac_grx, 23, 23);
1077	int gbit = EXTRACTED64(*frac_grx, 24, 24);
1078	int rbit = EXTRACTED64(*frac_grx, 25, 25);
1079	int xbit = EXTRACTED64(*frac_grx, 26, 55) != 0;
1080	if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
1081	  if (lsb == 1 && gbit == 1) inc = 1;
1082	  if (lsb == 0 && gbit == 1 && rbit == 1) inc = 1;
1083	  if (lsb == 0 && gbit == 1 && xbit == 1) inc = 1;
1084	}
1085	if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_pos_infinity) {
1086	  if (sign == 0 && gbit == 1) inc = 1;
1087	  if (sign == 0 && rbit == 1) inc = 1;
1088	  if (sign == 0 && xbit == 1) inc = 1;
1089	}
1090	if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_neg_infinity) {
1091	  if (sign == 1 && gbit == 1) inc = 1;
1092	  if (sign == 1 && rbit == 1) inc = 1;
1093	  if (sign == 1 && xbit == 1) inc = 1;
1094	}
1095	/* work out addition in low 25 bits of out */
1096	out = EXTRACTED64(*frac_grx, 0, 23) + inc;
1097	*frac_grx = INSERTED64(out, 0, 23);
1098	if (out & BIT64(64 - 23 - 1 - 1)) {
1099	  *frac_grx = (BIT64(0) |
1100	               INSERTED64(EXTRACTED64(*frac_grx, 0, 22), 1, 23));
1101	  *exp = *exp + 1;
1102	}
1103	/* frac_grx[24:52] = 0 already */
1104	FPSCR_SET_FR(inc);
1105	FPSCR_SET_FI(gbit || rbit || xbit);
1106
1107
1108#
1109void::function::Round_Integer:cpu *processor, int sign, unsigned64 *frac, int *frac64, int gbit, int rbit, int xbit, fpscreg round_mode
1110	int inc = 0;
1111	if (round_mode == fpscr_rn_round_to_nearest) {
1112	  if (*frac64 == 1 && gbit == 1) inc = 1;
1113	  if (*frac64 == 0 && gbit == 1 && rbit == 1) inc = 1;
1114	  if (*frac64 == 0 && gbit == 1 && xbit == 1) inc = 1;
1115	}
1116	if (round_mode == fpscr_rn_round_towards_pos_infinity) {
1117	  if (sign == 0 && gbit == 1) inc = 1;
1118	  if (sign == 0 && rbit == 1) inc = 1;
1119	  if (sign == 0 && xbit == 1) inc = 1;
1120	}
1121	if (round_mode == fpscr_rn_round_towards_neg_infinity) {
1122	  if (sign == 1 && gbit == 1) inc = 1;
1123	  if (sign == 1 && rbit == 1) inc = 1;
1124	  if (sign == 1 && xbit == 1) inc = 1;
1125	}
1126	/* frac[0:64] = frac[0:64} + inc */
1127	*frac += (*frac64 && inc ? 1 : 0);
1128	*frac64 = (*frac64 + inc) & 0x1;
1129	FPSCR_SET_FR(inc);
1130	FPSCR_SET_FI(gbit | rbit | xbit);
1131
1132
1133void::function::Round_Float:cpu *processor, int sign, int *exp, unsigned64 *frac, fpscreg round_mode
1134	int carry_out;
1135	int inc = 0;
1136	int lsb = EXTRACTED64(*frac, 52, 52);
1137	int gbit = EXTRACTED64(*frac, 53, 53);
1138	int rbit = EXTRACTED64(*frac, 54, 54);
1139	int xbit = EXTRACTED64(*frac, 55, 55);
1140	if (round_mode == fpscr_rn_round_to_nearest) {
1141	  if (lsb == 1 && gbit == 1) inc = 1;
1142	  if (lsb == 0 && gbit == 1 && rbit == 1) inc = 1;
1143	  if (lsb == 0 && gbit == 1 && xbit == 1) inc = 1;
1144	}
1145	if (round_mode == fpscr_rn_round_towards_pos_infinity) {
1146	  if (sign == 0 && gbit == 1) inc = 1;
1147	  if (sign == 0 && rbit == 1) inc = 1;
1148	  if (sign == 0 && xbit == 1) inc = 1;
1149	}
1150	if (round_mode == fpscr_rn_round_towards_neg_infinity) {
1151	  if (sign == 1 && gbit == 1) inc = 1;
1152	  if (sign == 1 && rbit == 1) inc = 1;
1153	  if (sign == 1 && xbit == 1) inc = 1;
1154	}
1155	/* frac//carry_out = frac + inc */
1156	*frac = (*frac >> 1) + (INSERTED64(inc, 52, 52) >> 1);
1157	carry_out = EXTRACTED64(*frac, 0, 0);
1158	*frac <<= 1;
1159	if (carry_out == 1) *exp = *exp + 1;
1160	FPSCR_SET_FR(inc);
1161	FPSCR_SET_FI(gbit | rbit | xbit);
1162	FPSCR_SET_XX(FPSCR & fpscr_fi);
1163
1164
1165# conversion of FP to integer
1166void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64 *frt, unsigned64 frb, fpscreg round_mode, int tgt_precision
1167	int i;
1168	int exp = 0;
1169	unsigned64 frac = 0;
1170	int frac64 = 0;
1171	int gbit = 0;
1172	int rbit = 0;
1173	int xbit = 0;
1174	int sign = EXTRACTED64(frb, 0, 0);
1175	/***/
1176	  if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 63) == 0)
1177	    GOTO(Infinity_Operand);
1178	  if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 0)
1179	    GOTO(SNaN_Operand);
1180	  if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 1)
1181	    GOTO(QNaN_Operand);
1182	  if (EXTRACTED64(frb, 1, 11) > 1086) GOTO(Large_Operand);
1183	  if (EXTRACTED64(frb, 1, 11) > 0) exp = EXTRACTED64(frb, 1, 11) - 1023;
1184	  if (EXTRACTED64(frb, 1, 11) == 0) exp = -1022;
1185	  if (EXTRACTED64(frb, 1, 11) > 0) { /* normal */
1186	    frac = BIT64(1) | INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
1187	    frac64 = 0;
1188	  }
1189	  if (EXTRACTED64(frb, 1, 11) == 0) { /* denorm */
1190	    frac = INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
1191	    frac64 = 0;
1192	  }
1193	  gbit = 0, rbit = 0, xbit = 0;
1194	  for (i = 1; i <= 63 - exp; i++) {
1195	    xbit = rbit | xbit;
1196	    rbit = gbit;
1197	    gbit = frac64;
1198	    frac64 = EXTRACTED64(frac, 63, 63);
1199	    frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63);
1200	  }
1201	  Round_Integer(processor, sign, &frac, &frac64, gbit, rbit, xbit, round_mode);
1202	  if (sign == 1) { /* frac[0:64] = ~frac[0:64] + 1 */
1203	    frac = ~frac;
1204	    frac64 ^= 1;
1205	    frac += (frac64 ? 1 : 0);
1206	    frac64 = (frac64 + 1) & 0x1;
1207	  }
1208	  if (tgt_precision == 32 /* can ignore frac64 in compare */
1209	      && (signed64)frac > (signed64)MASK64(33+1, 63)/*2^31-1 >>1*/)
1210	    GOTO(Large_Operand);
1211	  if (tgt_precision == 64 /* can ignore frac64 in compare */
1212	      && (signed64)frac > (signed64)MASK64(1+1, 63)/*2^63-1 >>1*/)
1213	    GOTO(Large_Operand);
1214	  if (tgt_precision == 32 /* can ignore frac64 in compare */
1215	      && (signed64)frac < (signed64)MASK64(0, 32+1)/*-2^31 >>1*/)
1216	    GOTO(Large_Operand);
1217	  if (tgt_precision == 64 /* can ignore frac64 in compare */
1218	      && (signed64)frac < (signed64)MASK64(0, 0+1)/*-2^63 >>1*/)
1219	    GOTO(Large_Operand);
1220	  FPSCR_SET_XX(FPSCR & fpscr_fi);
1221	  if (tgt_precision == 32)
1222	    *frt = MASKED64(*frt, 0, 31) | (EXTRACTED64(frac, 33, 63) << 1) | frac64;
1223	  if (tgt_precision == 64)
1224	    *frt = (EXTRACTED64(frac, 1, 63) << 1) | frac64;
1225	  /*FPSCR[fprf] = undefined */
1226	  GOTO(Done);
1227	  /**/
1228	LABEL(Infinity_Operand):
1229	  FPSCR_SET_FR(0);
1230	  FPSCR_SET_FI(0);
1231	  FPSCR_OR_VX(fpscr_vxcvi);
1232	  if ((FPSCR & fpscr_ve) == 0) {
1233	    if (tgt_precision == 32) {
1234	      if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7FFFFFFF;
1235	      if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1236	    }
1237	    else {
1238	      if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/
1239	      if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
1240	    }
1241	    /* FPSCR[FPRF] = undefined */
1242	  }
1243	  GOTO(Done);
1244	/**/
1245	LABEL(SNaN_Operand):
1246	  FPSCR_SET_FR(0);
1247	  FPSCR_SET_FI(0);
1248	  FPSCR_OR_VX(fpscr_vxsnan | fpscr_vxcvi);
1249	  if ((FPSCR & fpscr_ve) == 0) {
1250	    if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1251	    if (tgt_precision == 64) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
1252	    /* FPSCR[fprf] = undefined */
1253	  }
1254	  GOTO(Done);
1255	/**/
1256	LABEL(QNaN_Operand):
1257	  FPSCR_SET_FR(0);
1258	  FPSCR_SET_FI(0);
1259	  FPSCR_OR_VX(fpscr_vxcvi);
1260	  if ((FPSCR & fpscr_ve) == 0) {
1261	    if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1262	    if (tgt_precision == 64) *frt = BIT64(0);/*0x8000_0000_0000_0000*/
1263	    /* FPSCR[fprf] = undefined */
1264	  }
1265	  GOTO(Done);
1266	/**/
1267	LABEL(Large_Operand):
1268	  FPSCR_SET_FR(0);
1269	  FPSCR_SET_FI(0);
1270	  FPSCR_OR_VX(fpscr_vxcvi);
1271	  if ((FPSCR & fpscr_ve) == 0) {
1272	    if (tgt_precision == 32) {
1273	      if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7fffffff;
1274	      if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1275	    }
1276	    else {
1277	      if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/
1278	      if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
1279	    }
1280	    /* FPSCR[fprf] = undefined */
1281	  }
1282	/**/
1283	LABEL(Done):;
1284
1285
1286# extract out raw fields of a FP number
1287int::function::sign:unsigned64 FRS
1288	return (MASKED64(FRS, 0, 0)
1289	        ? -1
1290	        : 1);
1291int::function::biased_exp:unsigned64 frs, int single
1292	if (single)
1293	  return EXTRACTED64(frs, 1, 8);
1294	else
1295	  return EXTRACTED64(frs, 1, 11);
1296unsigned64::function::fraction:unsigned64 frs, int single
1297	if (single)
1298	  return EXTRACTED64(frs, 9, 31);
1299	else
1300	  return EXTRACTED64(frs, 12, 63);
1301
1302# a number?, each of the below return +1 or -1 (based on sign bit)
1303# if true.
1304int::function::is_nor:unsigned64 frs, int single
1305	int exp = biased_exp(frs, single);
1306	return (exp >= 1
1307	        && exp <= (single ? 254 : 2046));
1308int::function::is_zero:unsigned64 FRS
1309	return (MASKED64(FRS, 1, 63) == 0
1310	        ? sign(FRS)
1311	        : 0);
1312int::function::is_den:unsigned64 frs, int single
1313	int exp = biased_exp(frs, single);
1314	unsigned64 frac = fraction(frs, single);
1315	return (exp == 0 && frac != 0
1316	        ? sign(frs)
1317	        : 0);
1318int::function::is_inf:unsigned64 frs, int single
1319	int exp = biased_exp(frs, single);
1320	unsigned64 frac = fraction(frs, single);
1321	return (exp == (single ? 255 : 2047) && frac == 0
1322	        ? sign(frs)
1323	        : 0);
1324int::function::is_NaN:unsigned64 frs, int single
1325	int exp = biased_exp(frs, single);
1326	unsigned64 frac = fraction(frs, single);
1327	return (exp == (single ? 255 : 2047) && frac != 0
1328	        ? sign(frs)
1329	        : 0);
1330int::function::is_SNaN:unsigned64 frs, int single
1331	return (is_NaN(frs, single)
1332	        && !(frs & (single ? MASK64(9, 9) : MASK64(12, 12)))
1333	             ? sign(frs)
1334	             : 0);
1335int::function::is_QNaN:unsigned64 frs, int single
1336	return (is_NaN(frs, single) && !is_SNaN(frs, single));
1337int::function::is_less_than:unsigned64 *fra, unsigned64 *frb
1338	return *(double*)fra < *(double*)frb;
1339int::function::is_greater_than:unsigned64 *fra, unsigned64 *frb
1340	return *(double*)fra > *(double*)frb;
1341int::function::is_equan_to:unsigned64 *fra, unsigned64 *frb
1342	return *(double*)fra == *(double*)frb;
1343
1344
1345# which quiet nan should become the result
1346unsigned64::function::select_qnan:unsigned64 fra, unsigned64 frb, unsigned64 frc, int instruction_is_frsp, int generate_qnan, int single
1347	unsigned64 frt = 0;
1348	if (is_NaN(fra, single))
1349	  frt = fra;
1350	else if (is_NaN(frb, single))
1351	  if (instruction_is_frsp)
1352	    frt = MASKED64(frb, 0, 34);
1353	  else
1354	    frt = frb;
1355	else if (is_NaN(frc, single))
1356	  frt = frc;
1357	else if (generate_qnan)
1358	  frt = MASK64(1, 12); /* 0x7FF8_0000_0000_0000 */
1359	else
1360	  error("select_qnan - default reached\n");
1361	return frt;
1362
1363
1364# detect invalid operation
1365int::function::is_invalid_operation:cpu *processor, unsigned_word cia, unsigned64 fra, unsigned64 frb, fpscreg check, int single, int negate
1366	int fail = 0;
1367	if ((check & fpscr_vxsnan)
1368	    && (is_SNaN(fra, single) || is_SNaN(frb, single))) {
1369	  FPSCR_OR_VX(fpscr_vxsnan);
1370	  fail = 1;
1371	}
1372	if ((check & fpscr_vxisi)
1373	    && (is_inf(fra, single) && is_inf(frb, single))
1374	    && ((negate && sign(fra) != sign(frb))
1375	        || (!negate && sign(fra) == sign(frb)))) {
1376	   /*FIXME: don't handle inf-inf VS inf+-inf */
1377	  FPSCR_OR_VX(fpscr_vxisi);
1378	  fail = 1;
1379	}
1380	if ((check & fpscr_vxidi)
1381	    && (is_inf(fra, single) && is_inf(frb, single))) {
1382	  FPSCR_OR_VX(fpscr_vxidi);
1383	  fail = 1;
1384	}
1385	if ((check & fpscr_vxzdz)
1386	    && (is_zero(fra) && is_zero(frb))) {
1387	  FPSCR_OR_VX(fpscr_vxzdz);
1388	  fail = 1;
1389	}
1390	if ((check & fpscr_vximz)
1391	    && (is_zero(fra) && is_inf(frb, single))) {
1392	  FPSCR_OR_VX(fpscr_vximz);
1393	  fail = 1;
1394	}
1395	if ((check & fpscr_vxvc)
1396	    && (is_NaN(fra, single) || is_NaN(frb, single))) {
1397	  FPSCR_OR_VX(fpscr_vxvc);
1398	  fail = 1;
1399	}
1400	if ((check & fpscr_vxsoft)) {
1401	  FPSCR_OR_VX(fpscr_vxsoft);
1402	  fail = 1;
1403	}
1404	if ((check & fpscr_vxsqrt)
1405	    && sign(fra) < 0) {
1406	  FPSCR_OR_VX(fpscr_vxsqrt);
1407	  fail = 1;
1408	}
1409	/* if ((check && fpscr_vxcvi) {
1410	    && (is_inf(fra, single) || is_NaN(fra, single) || is_large(fra, single)))
1411	  FPSCR_OR_VX(fpscr_vxcvi);
1412	  fail = 1;
1413	}
1414	*/
1415	return fail;
1416
1417
1418
1419
1420
1421# handle case of invalid operation
1422void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, unsigned64 *frt, unsigned64 fra, unsigned64 frb, unsigned64 frc, int instruction_is_frsp, int instruction_is_convert_to_64bit, int instruction_is_convert_to_32bit, int single
1423	if (FPSCR & fpscr_ve) {
1424	  /* invalid operation exception enabled */
1425	  /* FRT unchaged */
1426	  FPSCR_SET_FR(0);
1427	  FPSCR_SET_FI(0);
1428	  /* fpscr_FPRF unchanged */
1429	}
1430	else {
1431	  /* invalid operation exception disabled */
1432	  if (instruction_is_convert_to_64bit) {
1433	    error("oopsi");
1434	  }
1435	  else if (instruction_is_convert_to_32bit) {
1436	    error("oopsi");
1437	  }
1438	  else { /* arrith, frsp */
1439	    *frt = select_qnan(fra, frb, frc,
1440	                       instruction_is_frsp, 1/*generate*/, single);
1441	    FPSCR_SET_FR(0);
1442	    FPSCR_SET_FI(0);
1443	    FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
1444	  }
1445	}
1446
1447
1448
1449
1450# detect divide by zero
1451int::function::is_invalid_zero_divide:cpu *processor, unsigned_word cia, unsigned64 fra, unsigned64 frb, int single
1452	int fail = 0;
1453	if (is_zero (frb)) {
1454	  FPSCR_SET_ZX (1);
1455	  fail = 1;
1456	}
1457	return fail;
1458
1459
1460
1461
1462# handle case of invalid operation
1463void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, unsigned64 *frt, unsigned64 fra, unsigned64 frb, int single
1464	if (FPSCR & fpscr_ze) {
1465	  /* zero-divide exception enabled */
1466	  /* FRT unchaged */
1467	  FPSCR_SET_FR(0);
1468	  FPSCR_SET_FI(0);
1469	  /* fpscr_FPRF unchanged */
1470	}
1471	else {
1472	  /* zero-divide exception disabled */
1473	  FPSCR_SET_FR(0);
1474	  FPSCR_SET_FI(0);
1475	  if ((sign (fra) < 0 && sign (frb) < 0)
1476	      || (sign (fra) > 0 && sign (frb) > 0)) {
1477	    *frt = MASK64 (1, 11); /* 0 : 2047 : 0..0 */
1478	    FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
1479	  }
1480	  else {
1481	    *frt = MASK64 (0, 11); /* 1 : 2047 : 0..0 */
1482	    FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
1483	  }
1484	}
1485
1486
1487
1488
1489
1490#
1491# 0.0.0.0 Illegal instruction used for kernel mode emulation
1492#
14930.0,6./,11./,16./,21./,31.1:X:::instruction_call
1494	if (!os_emul_instruction_call(processor, cia, real_addr(cia, 1)))
1495	  program_interrupt(processor, cia,
1496	                    illegal_instruction_program_interrupt);
1497
1498#
1499# I.2.4.1 Branch Instructions
1500#
15010.18,6.LI,30.AA,31.LK:I:::Branch
1502*601: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1503*603: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1504*603e:PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1505*604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1506	/* option_mpc860c0:
1507	No problem here because this branch is predicted taken (unconditional). */
1508	if (AA) NIA = IEA(EXTS(LI_0b00));
1509	else    NIA = IEA(CIA + EXTS(LI_0b00));
1510	if (LK) LR = (spreg)CIA+4;
1511	if (CURRENT_MODEL_ISSUE > 0)
1512	  model_branches(cpu_model(processor), 1, -1);
1513
15140.16,6.BO,11.BI,16.BD,30.AA,31.LK:B:::Branch Conditional
1515*601: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1516*603: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1517*603e:PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1518*604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1519	int M, ctr_ok, cond_ok, succeed;
1520	if (CURRENT_MODEL_ISSUE > 0 && ! BO{0})
1521	  model_wait_for_cr(cpu_model(processor), BIT32_BI);
1522	if (is_64bit_implementation && is_64bit_mode) M = 0;
1523	else                                          M = 32;
1524	if (!BO{2}) CTR = CTR - 1;
1525	ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != (BO{3}));
1526	cond_ok = BO{0} || ((CR{BI}) == (BO{1}));
1527	if (ctr_ok && cond_ok) {
1528	  if (AA) NIA = IEA(EXTS(BD_0b00));
1529	  else    NIA = IEA(CIA + EXTS(BD_0b00));
1530	  succeed = 1;
1531	}
1532	else
1533	  succeed = 0;
1534	if (LK) LR = (spreg)IEA(CIA + 4);
1535	if (option_mpc860c0 && (!BO{0} || !BO{2}) && !BO{4}) {
1536	  /* This branch is predicted as "normal".
1537	  If this is a forward branch and it is near the end of a page,
1538	  we've detected a problematic branch. */
1539	  if (succeed && NIA > CIA) {
1540	    if (PAGE_SIZE - (CIA & (PAGE_SIZE-1)) <= option_mpc860c0)
1541	      program_interrupt(processor, cia, mpc860c0_instruction_program_interrupt);
1542	  }
1543	}
1544	if (CURRENT_MODEL_ISSUE > 0)
1545	  model_branches(cpu_model(processor), succeed, BO);
1546	if (! BO{0}) {
1547	  int reverse;
1548	  if (BO{4}) {	/* branch prediction bit set, reverse sense of test */
1549	    reverse = EXTS(BD_0b00) < 0;
1550	  } else {	/* branch prediction bit not set */
1551	    reverse = EXTS(BD_0b00) >= 0;
1552	  }
1553	  if (CURRENT_MODEL_ISSUE > 0)
1554	    model_branch_predict(cpu_model(processor), reverse ? !succeed : succeed);
1555	}
1556
15570.19,6.BO,11.BI,16./,21.16,31.LK:XL:::Branch Conditional to Link Register
1558*601: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1559*603: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1560*603e:PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1561*604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1562	int M, ctr_ok, cond_ok, succeed;
1563	if (is_64bit_implementation && is_64bit_mode) M = 0;
1564	else                                          M = 32;
1565	if (CURRENT_MODEL_ISSUE > 0 && ! BO{0})
1566	  model_wait_for_cr(cpu_model(processor), BIT32_BI);
1567	if (!BO{2}) CTR = CTR - 1;
1568	ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != BO{3});
1569	cond_ok = BO{0} || (CR{BI} == BO{1});
1570	if (ctr_ok && cond_ok) {
1571	  NIA = IEA(LR_0b00);
1572	  succeed = 1;
1573	}
1574	else
1575	  succeed = 0;
1576	if (LK) LR = (spreg)IEA(CIA + 4);
1577	if (option_mpc860c0 && (!BO{0} || !BO{2}) && !BO{4}) {
1578	  /* This branch is predicted as not-taken.
1579	  If this is a forward branch and it is near the end of a page,
1580	  we've detected a problematic branch. */
1581	  if (succeed && NIA > CIA) {
1582	    if (PAGE_SIZE - (CIA & (PAGE_SIZE-1)) <= option_mpc860c0)
1583	      program_interrupt(processor, cia, mpc860c0_instruction_program_interrupt);
1584	  }
1585	}
1586	if (CURRENT_MODEL_ISSUE > 0) {
1587	  model_branches(cpu_model(processor), succeed, BO);
1588	  if (! BO{0})
1589	    model_branch_predict(cpu_model(processor), BO{4} ? !succeed : succeed);
1590	}
1591
15920.19,6.BO,11.BI,16./,21.528,31.LK:XL:::Branch Conditional to Count Register
1593*601: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1594*603: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1595*603e:PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1596*604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1597	int cond_ok, succeed;
1598	if (CURRENT_MODEL_ISSUE > 0 && ! BO{0})
1599	  model_wait_for_cr(cpu_model(processor), BIT32_BI);
1600	cond_ok = BO{0} || (CR{BI} == BO{1});
1601	if (cond_ok) {
1602	  NIA = IEA(CTR_0b00);
1603	  succeed = 1;
1604	}
1605	else
1606	  succeed = 0;
1607	if (LK) LR = (spreg)IEA(CIA + 4);
1608	if (option_mpc860c0 && (!BO{0} || !BO{2}) && !BO{4}) {
1609	  /* This branch is predicted as not-taken.
1610	  If this is a forward branch and it is near the end of a page,
1611	  we've detected a problematic branch. */
1612	  if (succeed && NIA > CIA) {
1613	    if (PAGE_SIZE - (CIA & (PAGE_SIZE-1)) <= option_mpc860c0)
1614	      program_interrupt(processor, cia, mpc860c0_instruction_program_interrupt);
1615	  }
1616	}
1617	if (CURRENT_MODEL_ISSUE > 0) {
1618	  model_branches(cpu_model(processor), succeed, BO);
1619	  if (! BO{0})
1620	    model_branch_predict(cpu_model(processor), BO{4} ? !succeed : succeed);
1621	}
1622
1623#
1624# I.2.4.2 System Call Instruction
1625#
16260.17,6./,11./,16./,30.1,31./:SC:::System Call
1627*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1628*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   3,  3,  0
1629*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   3,  3,  0
1630*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
1631	if (CURRENT_MODEL_ISSUE > 0)
1632	  model_serialize(MY_INDEX, cpu_model(processor));
1633	system_call_interrupt(processor, cia);
1634
1635#
1636# I.2.4.3 Condition Register Logical Instructions
1637#
16380.19,6.BT,11.BA,16.BB,21.257,31./:XL::crand:Condition Register AND
1639*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1640*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1641*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1642*604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1643	BLIT32(CR, BT, CR{BA} && CR{BB});
1644	PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1645
16460.19,6.BT,11.BA,16.BB,21.449,31./:XL::cror:Condition Register OR
1647*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1648*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1649*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1650*604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1651	BLIT32(CR, BT, CR{BA} || CR{BB});
1652	PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1653
16540.19,6.BT,11.BA,16.BB,21.193,31./:XL::crxor:Condition Register XOR
1655*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1656*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1657*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1658*604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1659	BLIT32(CR, BT, CR{BA} != CR{BB});
1660	PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1661
16620.19,6.BT,11.BA,16.BB,21.225,31./:XL::crnand:Condition Register NAND
1663*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1664*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1665*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1666*604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1667	BLIT32(CR, BT, !(CR{BA} && CR{BB}));
1668	PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1669
16700.19,6.BT,11.BA,16.BB,21.33,31./:XL::crnor:Condition Register NOR
1671*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1672*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1673*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1674*604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1675	BLIT32(CR, BT, !(CR{BA} || CR{BB}));
1676	PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1677
16780.19,6.BT,11.BA,16.BB,21.289,31./:XL::creqv:Condition Register Equivalent
1679*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1680*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1681*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1682*604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1683	BLIT32(CR, BT, CR{BA} == CR{BB});
1684	PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1685
16860.19,6.BT,11.BA,16.BB,21.129,31./:XL::crandc:Condition Register AND with Complement
1687*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1688*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1689*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1690*604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1691	BLIT32(CR, BT, CR{BA} && !CR{BB});
1692	PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1693
16940.19,6.BT,11.BA,16.BB,21.417,31./:XL::crorc:Condition Register OR with Complement
1695*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1696*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1697*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1698*604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1699	BLIT32(CR, BT, CR{BA} || !CR{BB});
1700	PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1701
1702#
1703# I.2.4.4 Condition Register Field Instruction
1704#
17050.19,6.BF,9./,11.BFA,14./,16./,21.0,31./:XL:::Move Condition Register Field
1706*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1707*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1708*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1709*604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1710	MBLIT32(CR, 4*BF, 4*BF+3, EXTRACTED32(CR, 4*BFA, 4*BFA+3));
1711	PPC_INSN_CR(BF_BITMASK, 1 << BFA);
1712
1713
1714#
1715# I.3.3.2 Fixed-Point Load Instructions
1716#
1717
17180.34,6.RT,11.RA,16.D:D:::Load Byte and Zero
1719*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1720*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1721*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1722*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1723	unsigned_word b;
1724	unsigned_word EA;
1725	if (RA_is_0) b = 0;
1726	else         b = *rA;
1727	EA = b + EXTS(D);
1728	*rT = MEM(unsigned, EA, 1);
1729	PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
1730
1731
17320.31,6.RT,11.RA,16.RB,21.87,31./:X:::Load Byte and Zero Indexed
1733*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1734*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1735*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1736*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1737	unsigned_word b;
1738	unsigned_word EA;
1739	if (RA_is_0) b = 0;
1740	else         b = *rA;
1741	EA = b + *rB;
1742	*rT = MEM(unsigned, EA, 1);
1743	PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
1744
17450.35,6.RT,11.RA,16.D:D:::Load Byte and Zero with Update
1746*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1747*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1748*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1749*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1750	unsigned_word EA;
1751	if (RA_is_0 || RA == RT)
1752	  program_interrupt(processor, cia,
1753	                    illegal_instruction_program_interrupt);
1754	EA = *rA + EXTS(D);
1755	*rT = MEM(unsigned, EA, 1);
1756	*rA = EA;
1757	PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK, 0);
1758
17590.31,6.RT,11.RA,16.RB,21.119,31./:X:::Load Byte and Zero with Update Indexed
1760*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1761*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1762*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1763*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1764	unsigned_word EA;
1765	if (RA_is_0 || RA == RT)
1766	  program_interrupt(processor, cia,
1767	                    illegal_instruction_program_interrupt);
1768	EA = *rA + *rB;
1769	*rT = MEM(unsigned, EA, 1);
1770	*rA = EA;
1771	PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK | RB_BITMASK, 0);
1772
17730.40,6.RT,11.RA,16.D:D:::Load Halfword and Zero
1774*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1775*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1776*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1777*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1778	unsigned_word b;
1779	unsigned_word EA;
1780	if (RA_is_0) b = 0;
1781	else         b = *rA;
1782	EA = b + EXTS(D);
1783	*rT = MEM(unsigned, EA, 2);
1784	PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
1785
17860.31,6.RT,11.RA,16.RB,21.279,31./:X:::Load Halfword and Zero Indexed
1787*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1788*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1789*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1790*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1791	unsigned_word b;
1792	unsigned_word EA;
1793	if (RA_is_0) b = 0;
1794	else         b = *rA;
1795	EA = b + *rB;
1796	*rT = MEM(unsigned, EA, 2);
1797	PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
1798
17990.41,6.RT,11.RA,16.D:D:::Load Halfword and Zero with Update
1800*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1801*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1802*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1803*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1804	unsigned_word EA;
1805	if (RA_is_0 || RA == RT)
1806	  program_interrupt(processor, cia,
1807	                    illegal_instruction_program_interrupt);
1808	EA = *rA + EXTS(D);
1809	*rT = MEM(unsigned, EA, 2);
1810	*rA = EA;
1811	PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK, 0);
1812
18130.31,6.RT,11.RA,16.RB,21.311,31./:X:::Load Halfword and Zero with Update Indexed
1814*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1815*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1816*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1817*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1818	unsigned_word EA;
1819	if (RA_is_0 || RA == RT)
1820	  program_interrupt(processor, cia,
1821	                    illegal_instruction_program_interrupt);
1822	EA = *rA + *rB;
1823	*rT = MEM(unsigned, EA, 2);
1824	*rA = EA;
1825	PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK | RB_BITMASK, 0);
1826
18270.42,6.RT,11.RA,16.D:D:::Load Halfword Algebraic
1828*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1829*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1830*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1831*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1832	unsigned_word b;
1833	unsigned_word EA;
1834	if (RA_is_0) b = 0;
1835	else         b = *rA;
1836	EA = b + EXTS(D);
1837	*rT = MEM(signed, EA, 2);
1838	PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
1839
18400.31,6.RT,11.RA,16.RB,21.343,31./:X:::Load Halfword Algebraic Indexed
1841*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1842*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1843*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1844*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1845	unsigned_word b;
1846	unsigned_word EA;
1847	if (RA_is_0) b = 0;
1848	else         b = *rA;
1849	EA = b + *rB;
1850	*rT = MEM(signed, EA, 2);
1851	PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
1852
18530.43,6.RT,11.RA,16.D:D:::Load Halfword Algebraic with Update
1854*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1855*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1856*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1857*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1858	unsigned_word EA;
1859	if (RA_is_0 || RA == RT)
1860	  program_interrupt(processor, cia,
1861	                    illegal_instruction_program_interrupt);
1862	EA = *rA + EXTS(D);
1863	*rT = MEM(signed, EA, 2);
1864	*rA = EA;
1865	PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK, 0);
1866
18670.31,6.RT,11.RA,16.RB,21.375,31./:X:::Load Halfword Algebraic with Update Indexed
1868*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1869*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1870*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1871*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1872	unsigned_word EA;
1873	if (RA_is_0 || RA == RT)
1874	  program_interrupt(processor, cia,
1875	                    illegal_instruction_program_interrupt);
1876	EA = *rA + *rB;
1877	*rT = MEM(signed, EA, 2);
1878	*rA = EA;
1879	PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK | RB_BITMASK, 0);
1880
18810.32,6.RT,11.RA,16.D:D:::Load Word and Zero
1882*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1883*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1884*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1885*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1886	unsigned_word b;
1887	unsigned_word EA;
1888	if (RA_is_0) b = 0;
1889	else         b = *rA;
1890	EA = b + EXTS(D);
1891	*rT = MEM(unsigned, EA, 4);
1892	PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
1893
18940.31,6.RT,11.RA,16.RB,21.23,31./:X:::Load Word and Zero Indexed
1895*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1896*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1897*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1898*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1899	unsigned_word b;
1900	unsigned_word EA;
1901	if (RA_is_0) b = 0;
1902	else         b = *rA;
1903	EA = b + *rB;
1904	*rT = MEM(unsigned, EA, 4);
1905	PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
1906
19070.33,6.RT,11.RA,16.D:D:::Load Word and Zero with Update
1908*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1909*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1910*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1911*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1912	unsigned_word EA;
1913	if (RA_is_0 || RA == RT)
1914	  program_interrupt(processor, cia,
1915	                    illegal_instruction_program_interrupt);
1916	EA = *rA + EXTS(D);
1917	*rT = MEM(unsigned, EA, 4);
1918	*rA = EA;
1919	PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK, 0);
1920
19210.31,6.RT,11.RA,16.RB,21.55,31./:X:::Load Word and Zero with Update Indexed
1922*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1923*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1924*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1925*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1926	unsigned_word EA;
1927	if (RA_is_0 || RA == RT)
1928	  program_interrupt(processor, cia,
1929	                    illegal_instruction_program_interrupt);
1930	EA = *rA + *rB;
1931	*rT = MEM(unsigned, EA, 4);
1932	*rA = EA;
1933	PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK | RB_BITMASK, 0);
1934
19350.58,6.RT,11.RA,16.DS,30.2:DS:64::Load Word Algebraic
1936#	unsigned_word b;
1937#	unsigned_word EA;
1938#	if (RA_is_0) b = 0;
1939#	else         b = *rA;
1940#	EA = b + EXTS(DS_0b00);
1941#	*rT = MEM(signed, EA, 4);
1942
19430.31,6.RT,11.RA,16.RB,21.341,31./:X:64::Load Word Algebraic Indexed
1944#	unsigned_word b;
1945#	unsigned_word EA;
1946#	if (RA_is_0) b = 0;
1947#	else         b = *rA;
1948#	EA = b + *rB;;
1949#	*rT = MEM(signed, EA, 4);
1950
19510.31,6.RT,11.RA,16.RB,21.373,31./:X:64::Load Word Algebraic with Update Indexed
1952#	unsigned_word EA;
1953#	if (RA_is_0 || RA == RT)
1954#	  program_interrupt(processor, cia
1955#	                    illegal_instruction_program_interrupt);
1956#	EA = *rA + *rB;
1957#	*rT = MEM(signed, EA, 4);
1958#	*rA = EA;
1959
19600.58,6.RT,11.RA,16.DS,30.0:DS:64::Load Doubleword
1961#	unsigned_word b;
1962#	unsigned_word EA;
1963#	if (RA_is_0) b = 0;
1964#	else         b = *rA;
1965#	EA = b + EXTS(DS_0b00);
1966#	*rT = MEM(unsigned, EA, 8);
1967
19680.31,6.RT,11.RA,16.RB,21.21,31./:X:64::Load Doubleword Indexed
1969#	unsigned_word b;
1970#	unsigned_word EA;
1971#	if (RA_is_0) b = 0;
1972#	else         b = *rA;
1973#	EA = b + *rB;
1974#	*rT = MEM(unsigned, EA, 8);
1975
19760.58,6.RT,11.RA,16.DS,30.1:DS:64::Load Doubleword with Update
1977#	unsigned_word EA;
1978#	if (RA_is_0 || RA == RT)
1979#	  program_interrupt(processor, cia
1980#	                    illegal_instruction_program_interrupt);
1981#	EA = *rA + EXTS(DS_0b00);
1982#	*rT = MEM(unsigned, EA, 8);
1983#	*rA = EA;
1984
19850.31,6.RT,11.RA,16.RB,21.53,31./:DS:64::Load Doubleword with Update Indexed
1986#	unsigned_word EA;
1987#	if (RA_is_0 || RA == RT)
1988#	  program_interrupt(processor, cia
1989#	                    illegal_instruction_program_interrupt);
1990#	EA = *rA + *rB;
1991#	*rT = MEM(unsigned, EA, 8);
1992#	*rA = EA;
1993
1994
1995
1996#
1997# I.3.3.3 Fixed-Point Store Instructions
1998#
1999
20000.38,6.RS,11.RA,16.D:D:::Store Byte
2001*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2002*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2003*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2004*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
2005	unsigned_word b;
2006	unsigned_word EA;
2007	if (RA_is_0) b = 0;
2008	else         b = *rA;
2009	EA = b + EXTS(D);
2010	STORE(EA, 1, *rS);
2011	PPC_INSN_INT(0, (RA_BITMASK & ~1) | RS_BITMASK, 0);
2012
20130.31,6.RS,11.RA,16.RB,21.215,31./:X:::Store Byte Indexed
2014*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2015*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2016*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2017*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
2018	unsigned_word b;
2019	unsigned_word EA;
2020	if (RA_is_0) b = 0;
2021	else         b = *rA;
2022	EA = b + *rB;
2023	STORE(EA, 1, *rS);
2024	PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
2025
20260.39,6.RS,11.RA,16.D:D:::Store Byte with Update
2027*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2028*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2029*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2030*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
2031	unsigned_word EA;
2032	if (RA_is_0)
2033	  program_interrupt(processor, cia,
2034	                    illegal_instruction_program_interrupt);
2035	EA = *rA + EXTS(D);
2036	STORE(EA, 1, *rS);
2037	*rA = EA;
2038	PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RS_BITMASK, 0);
2039
20400.31,6.RS,11.RA,16.RB,21.247,31./:X:::Store Byte with Update Indexed
2041*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2042*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2043*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2044*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
2045	unsigned_word EA;
2046	if (RA_is_0)
2047	  program_interrupt(processor, cia,
2048	                    illegal_instruction_program_interrupt);
2049	EA = *rA + *rB;
2050	STORE(EA, 1, *rS);
2051	*rA = EA;
2052	PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RB_BITMASK | RS_BITMASK, 0);
2053
20540.44,6.RS,11.RA,16.D:D:::Store Half Word
2055*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2056*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2057*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2058*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
2059	unsigned_word b;
2060	unsigned_word EA;
2061	if (RA_is_0) b = 0;
2062	else         b = *rA;
2063	EA = b + EXTS(D);
2064	STORE(EA, 2, *rS);
2065	PPC_INSN_INT(0, (RA_BITMASK & ~1) | RS_BITMASK, 0);
2066
20670.31,6.RS,11.RA,16.RB,21.407,31./:X:::Store Half Word Indexed
2068*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2069*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2070*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2071*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
2072	unsigned_word b;
2073	unsigned_word EA;
2074	if (RA_is_0) b = 0;
2075	else         b = *rA;
2076	EA = b + *rB;
2077	STORE(EA, 2, *rS);
2078	PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
2079
20800.45,6.RS,11.RA,16.D:D:::Store Half Word with Update
2081*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2082*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2083*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2084*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
2085	unsigned_word EA;
2086	if (RA_is_0)
2087	  program_interrupt(processor, cia,
2088	                    illegal_instruction_program_interrupt);
2089	EA = *rA + EXTS(D);
2090	STORE(EA, 2, *rS);
2091	*rA = EA;
2092	PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RS_BITMASK, 0);
2093
20940.31,6.RS,11.RA,16.RB,21.439,31./:X:::Store Half Word with Update Indexed
2095*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2096*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2097*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2098*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
2099	unsigned_word EA;
2100	if (RA_is_0)
2101	  program_interrupt(processor, cia,
2102	                    illegal_instruction_program_interrupt);
2103	EA = *rA + *rB;
2104	STORE(EA, 2, *rS);
2105	*rA = EA;
2106	PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RB_BITMASK | RS_BITMASK, 0);
2107
21080.36,6.RS,11.RA,16.D:D:::Store Word
2109*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2110*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2111*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2112*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
2113	unsigned_word b;
2114	unsigned_word EA;
2115	if (RA_is_0) b = 0;
2116	else         b = *rA;
2117	EA = b + EXTS(D);
2118	STORE(EA, 4, *rS);
2119	PPC_INSN_INT(0, (RA_BITMASK & ~1) | RS_BITMASK, 0);
2120
21210.31,6.RS,11.RA,16.RB,21.151,31./:X:::Store Word Indexed
2122*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2123*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2124*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2125*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
2126	unsigned_word b;
2127	unsigned_word EA;
2128	if (RA_is_0) b = 0;
2129	else         b = *rA;
2130	EA = b + *rB;
2131	STORE(EA, 4, *rS);
2132	PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
2133
21340.37,6.RS,11.RA,16.D:D:::Store Word with Update
2135*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2136*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2137*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2138*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
2139	unsigned_word EA;
2140	if (RA_is_0)
2141	  program_interrupt(processor, cia,
2142	                    illegal_instruction_program_interrupt);
2143	EA = *rA + EXTS(D);
2144	STORE(EA, 4, *rS);
2145	*rA = EA;
2146	PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RS_BITMASK, 0);
2147
21480.31,6.RS,11.RA,16.RB,21.183,31./:X:::Store Word with Update Indexed
2149*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2150*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2151*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2152*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
2153	unsigned_word EA;
2154	if (RA_is_0)
2155	  program_interrupt(processor, cia,
2156	                    illegal_instruction_program_interrupt);
2157	EA = *rA + *rB;
2158	STORE(EA, 4, *rS);
2159	*rA = EA;
2160	PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RB_BITMASK | RS_BITMASK, 0);
2161
21620.62,6.RS,11.RA,16.DS,30.0:DS:64::Store Doubleword
2163#	unsigned_word b;
2164#	unsigned_word EA;
2165#	if (RA_is_0) b = 0;
2166#	else         b = *rA;
2167#	EA = b + EXTS(DS_0b00);
2168#	STORE(EA, 8, *rS);
21690.31,6.RS,11.RA,16.RB,21.149,31./:X:64::Store Doubleword Indexed
2170#	unsigned_word b;
2171#	unsigned_word EA;
2172#	if (RA_is_0) b = 0;
2173#	else         b = *rA;
2174#	EA = b + *rB;
2175#	STORE(EA, 8, *rS);
21760.62,6.RS,11.RA,16.DS,30.1:DS:64::Store Doubleword with Update
2177#	unsigned_word EA;
2178#	if (RA_is_0)
2179#	  program_interrupt(processor, cia
2180#	                    illegal_instruction_program_interrupt);
2181#	EA = *rA + EXTS(DS_0b00);
2182#	STORE(EA, 8, *rS);
2183#	*rA = EA;
21840.31,6.RS,11.RA,16.RB,21.181,31./:X:64::Store Doubleword with Update Indexed
2185#	unsigned_word EA;
2186#	if (RA_is_0)
2187#	  program_interrupt(processor, cia
2188#	                    illegal_instruction_program_interrupt);
2189#	EA = *rA + *rB;
2190#	STORE(EA, 8, *rS);
2191#	*rA = EA;
2192
2193
2194#
2195# I.3.3.4 Fixed-Point Load and Store with Byte Reversal Instructions
2196#
2197
21980.31,6.RT,11.RA,16.RB,21.790,31./:X:::Load Halfword Byte-Reverse Indexed
2199*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2200*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2201*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2202*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
2203	unsigned_word b;
2204	unsigned_word EA;
2205	if (RA_is_0) b = 0;
2206	else         b = *rA;
2207	EA = b + *rB;
2208	*rT = SWAP_2(MEM(unsigned, EA, 2));
2209	PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
2210
22110.31,6.RT,11.RA,16.RB,21.534,31./:X:::Load Word Byte-Reverse Indexed
2212*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2213*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2214*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2215*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
2216	unsigned_word b;
2217	unsigned_word EA;
2218	if (RA_is_0) b = 0;
2219	else         b = *rA;
2220	EA = b + *rB;
2221	*rT = SWAP_4(MEM(unsigned, EA, 4));
2222	PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
2223
22240.31,6.RS,11.RA,16.RB,21.918,31./:X:::Store Half Word Byte-Reversed Indexed
2225*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2226*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2227*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2228*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
2229	unsigned_word b;
2230	unsigned_word EA;
2231	if (RA_is_0) b = 0;
2232	else         b = *rA;
2233	EA = b + *rB;
2234	STORE(EA, 2, SWAP_2(*rS));
2235	PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
2236
22370.31,6.RS,11.RA,16.RB,21.662,31./:X:::Store Word Byte-Reversed Indexed
2238*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2239*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2240*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2241*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
2242	unsigned_word b;
2243	unsigned_word EA;
2244	if (RA_is_0) b = 0;
2245	else         b = *rA;
2246	EA = b + *rB;
2247	STORE(EA, 4, SWAP_4(*rS));
2248	PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
2249
2250
2251#
2252# I.3.3.5 Fixed-Point Load and Store Multiple Instrctions
2253#
2254
22550.46,6.RT,11.RA,16.D:D:::Load Multiple Word
2256	unsigned_word EA;
2257	unsigned_word b;
2258	int r;
2259	if (RA_is_0) b = 0;
2260	else         b = *rA;
2261	EA = b + EXTS(D);
2262	r = RT;
2263	if (RA >= r)
2264	  program_interrupt(processor, cia,
2265	                  illegal_instruction_program_interrupt);
2266	if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT || (EA % 4 != 0))
2267	  alignment_interrupt(processor, cia, EA);
2268	while (r <= 31) {
2269	  GPR(r) = MEM(unsigned, EA, 4);
2270	  r = r + 1;
2271	  EA = EA + 4;
2272	}
2273
22740.47,6.RS,11.RA,16.D:D:::Store Multiple Word
2275	unsigned_word EA;
2276	unsigned_word b;
2277	int r;
2278	if (RA_is_0) b = 0;
2279	else         b = *rA;
2280	EA = b + EXTS(D);
2281	if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT
2282	    || (EA % 4 != 0))
2283	  alignment_interrupt(processor, cia, EA);
2284	r = RS;
2285	while (r <= 31) {
2286	  STORE(EA, 4, GPR(r));
2287	  r = r + 1;
2288	  EA = EA + 4;
2289	}
2290
2291
2292#
2293# I.3.3.6 Fixed-Point Move Assist Instructions
2294#
2295
22960.31,6.RT,11.RA,16.NB,21.597,31./:X:::Load String Word Immediate
2297	unsigned_word EA;
2298	int n;
2299	int r;
2300	int i;
2301	int nr;
2302	if (RA_is_0) EA = 0;
2303	else         EA = *rA;
2304	if (NB == 0) n = 32;
2305	else         n = NB;
2306	r = RT - 1;
2307	i = 32;
2308	nr = (n + 3) / 4;
2309	if ((RT + nr >= 32)
2310	    ? (RA >= RT || RA < (RT + nr) % 32)
2311	    : (RA >= RT && RA < RT + nr))
2312	  program_interrupt(processor, cia,
2313	                    illegal_instruction_program_interrupt);
2314	if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
2315	  alignment_interrupt(processor, cia, EA);
2316	while (n > 0) {
2317	  if (i == 32) {
2318	    r = (r + 1) % 32;
2319	    GPR(r) = 0;
2320	  }
2321	  GPR(r) |= INSERTED(MEM(unsigned, EA, 1), i, i+7);
2322	  i = i + 8;
2323	  if (i == 64) i = 32;
2324	  EA = EA + 1;
2325	  n = n - 1;
2326	}
2327
23280.31,6.RT,11.RA,16.RB,21.533,31./:X:::Load String Word Indexed
2329	unsigned_word EA;
2330	unsigned_word b;
2331	int n;
2332	int r;
2333	int i;
2334	int nr;
2335	if (RA_is_0) b = 0;
2336	else         b = *rA;
2337	EA = b + *rB;
2338	n = EXTRACTED32(XER, 25, 31);
2339	r = RT - 1;
2340	i = 32;
2341	nr = (n + 3) / 4;
2342	if (((RT + nr >= 32)
2343	     ? ((RA >= RT || RA < (RT + nr) % 32)
2344	        || (RB >= RT || RB < (RT + nr) % 32))
2345	     : ((RA >= RT && RA < RT + nr)
2346	        || (RB >= RT && RB < RT + nr)))
2347	    || (RT == RA || RT == RB))
2348	  program_interrupt(processor, cia,
2349	                  illegal_instruction_program_interrupt);
2350	if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
2351	  alignment_interrupt(processor, cia, EA);
2352	while (n > 0) {
2353	  if (i == 32) {
2354	    r = (r + 1) % 32;
2355	    GPR(r) = 0;
2356	  }
2357	  GPR(r) |= INSERTED(MEM(unsigned, EA, 1), i, i+7);
2358	  i = i + 8;
2359	  if (i == 64) i = 32;
2360	  EA = EA + 1;
2361	  n = n - 1;
2362	}
2363
23640.31,6.RS,11.RA,16.NB,21.725,31./:X:::Store String Word Immedate
2365	unsigned_word EA;
2366	int n;
2367	int r;
2368	int i;
2369	if (RA_is_0) EA = 0;
2370	else         EA = *rA;
2371	if (NB == 0) n = 32;
2372	else         n = NB;
2373	r = RS - 1;
2374	i = 32;
2375	if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
2376	  alignment_interrupt(processor, cia, EA);
2377	while (n > 0) {
2378	  if (i == 32) r = (r + 1) % 32;
2379	  STORE(EA, 1, EXTRACTED(GPR(r), i, i+7));
2380	  i = i + 8;
2381	  if (i == 64) i = 32;
2382	  EA = EA + 1;
2383	  n = n - 1;
2384	}
2385
23860.31,6.RS,11.RA,16.RB,21.661,31./:X:::Store String Word Indexed
2387	unsigned_word EA;
2388	unsigned_word b;
2389	int n;
2390	int r;
2391	int i;
2392	if (RA_is_0) b = 0;
2393	else         b = *rA;
2394	EA = b + *rB;
2395	if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
2396	  alignment_interrupt(processor, cia, EA);
2397	n = EXTRACTED32(XER, 25, 31);
2398	r = RS - 1;
2399	i = 32;
2400	while (n > 0) {
2401	  if (i == 32) r = (r + 1) % 32;
2402	  STORE(EA, 1, EXTRACTED(GPR(r), i, i+7));
2403	  i = i + 8;
2404	  if (i == 64) i = 32;
2405	  EA = EA + 1;
2406	  n = n - 1;
2407	}
2408
2409
2410#
2411# I.3.3.7 Storage Synchronization Instructions
2412#
2413# HACK: Rather than monitor addresses looking for a reason
2414#       to cancel a reservation.  This code instead keeps
2415#	a copy of the data read from memory.  Before performing
2416#	a store, the memory area is checked to see if it has
2417#	been changed.
24180.31,6.RT,11.RA,16.RB,21.20,31./:X:::Load Word And Reserve Indexed
2419*601: PPC_UNIT_IU,    PPC_UNIT_IU,    2,  2,  0
2420*603: PPC_UNIT_LSU,   PPC_UNIT_IU,    1,  2,  0
2421*603e:PPC_UNIT_LSU,   PPC_UNIT_IU,    1,  2,  0
2422*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
2423	unsigned_word b;
2424	unsigned_word EA;
2425	if (RA_is_0) b = 0;
2426	else         b = *rA;
2427	EA = b + *rB;
2428	RESERVE = 1;
2429	RESERVE_ADDR = real_addr(EA, 1/*is-read?*/);
2430	RESERVE_DATA = MEM(unsigned, EA, 4);
2431	*rT = RESERVE_DATA;
2432	PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
2433
24340.31,6.RT,11.RA,16.RB,21.84,31./:X:64::Load Doubleword And Reserve Indexed
2435	unsigned_word b;
2436	unsigned_word EA;
2437	if (RA_is_0) b = 0;
2438	else         b = *rA;
2439	EA = b + *rB;
2440	RESERVE = 1;
2441	RESERVE_ADDR = real_addr(EA, 1/*is-read?*/);
2442	RESERVE_DATA = MEM(unsigned, EA, 8);
2443	*rT = RESERVE_DATA;
2444	PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
2445
24460.31,6.RS,11.RA,16.RB,21.150,31.1:X:::Store Word Conditional Indexed
2447*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2448*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   8,  8,  0
2449*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   8,  8,  0
2450*604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  3,  0
2451	unsigned_word b;
2452	unsigned_word EA;
2453	if (RA_is_0) b = 0;
2454	else         b = *rA;
2455	EA = b + *rB;
2456	if (RESERVE) {
2457	  if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/)
2458	      && /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 4)) {
2459	    STORE(EA, 4, *rS);
2460	    CR_SET_XER_SO(0, cr_i_zero);
2461	  }
2462	  else {
2463	    /* ment to randomly to store, we never do! */
2464	    CR_SET_XER_SO(0, 0);
2465	  }
2466	  RESERVE = 0;
2467	}
2468	else {
2469	  CR_SET_XER_SO(0, 0);
2470	}
2471	PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 1/*Rc*/);
2472
24730.31,6.RS,11.RA,16.RB,21.214,31.1:X:64::Store Doubleword Conditional Indexed
2474	unsigned_word b;
2475	unsigned_word EA;
2476	if (RA_is_0) b = 0;
2477	else         b = *rA;
2478	EA = b + *rB;
2479	if (RESERVE) {
2480	  if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/)
2481	      && /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 8)) {
2482	    STORE(EA, 8, *rS);
2483	    CR_SET_XER_SO(0, cr_i_zero);
2484	  }
2485	  else {
2486	    /* ment to randomly to store, we never do */
2487	    CR_SET_XER_SO(0, 0);
2488	  }
2489	  RESERVE = 0;
2490	}
2491	else {
2492	  CR_SET_XER_SO(0, 0);
2493	}
2494	PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 1/*Rc*/);
2495
24960.31,6./,9.L,11./,16./,21.598,31./:X::sync:Synchronize
2497*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2498*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
2499*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
2500*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  1,  0
2501	/* do nothing */
2502
2503
2504#
2505# I.3.3.9 Fixed-Point Arithmetic Instructions
2506#
2507
25080.14,6.RT,11.RA,16.SI:D:::Add Immediate
2509*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2510*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2511*603e:PPC_UNIT_IU,    PPC_UNIT_SRU,   1,  1,  0
2512*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2513	if (RA_is_0)	*rT = EXTS(SI);
2514	else		*rT = *rA + EXTS(SI);
2515	ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rT, (long)*rT));
2516	PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
2517
25180.15,6.RT,11.RA,16.SI:D:::Add Immediate Shifted
2519*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2520*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2521*603e:PPC_UNIT_IU,    PPC_UNIT_SRU,   1,  1,  0
2522*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2523	if (RA_is_0)	*rT = EXTS(SI) << 16;
2524	else		*rT = *rA + (EXTS(SI) << 16);
2525	ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rT, (long)*rT));
2526	PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
2527
25280.31,6.RT,11.RA,16.RB,21.OE,22.266,31.Rc:XO:::Add
2529*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2530*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2531*603e:PPC_UNIT_IU,    PPC_UNIT_SRU,   1,  1,  0
2532*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2533	ALU_BEGIN(*rA);
2534	ALU_ADD(*rB);
2535	ALU_END(*rT, 0/*CA*/, OE, Rc);
2536	PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2537
25380.31,6.RT,11.RA,16.RB,21.OE,22.40,31.Rc:XO:::Subtract From
2539*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2540*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2541*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2542*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2543	ALU_BEGIN(*rA);
2544	ALU_NOT;
2545	ALU_ADD(*rB);
2546	ALU_ADD(1);
2547	ALU_END(*rT, 0/*CA*/, OE, Rc);
2548	PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2549
25500.12,6.RT,11.RA,16.SI:D:::Add Immediate Carrying
2551*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2552*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2553*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2554*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2555	ALU_BEGIN(*rA);
2556	ALU_ADD(EXTS(SI));
2557	ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
2558	PPC_INSN_INT(RT_BITMASK, RA_BITMASK, 0/*Rc*/);
2559
25600.13,6.RT,11.RA,16.SI:D:::Add Immediate Carrying and Record
2561*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2562*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2563*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2564*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2565	ALU_BEGIN(*rA);
2566	ALU_ADD(EXTS(SI));
2567	ALU_END(*rT, 1/*CA*/, 0/*OE*/, 1/*Rc*/);
2568	PPC_INSN_INT(RT_BITMASK, RA_BITMASK, 1/*Rc*/);
2569
25700.8,6.RT,11.RA,16.SI:D:::Subtract From Immediate Carrying
2571*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2572*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2573*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2574*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2575	ALU_BEGIN(*rA);
2576	ALU_NOT;
2577	ALU_ADD(EXTS(SI));
2578	ALU_ADD(1);
2579	ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
2580	PPC_INSN_INT(RT_BITMASK, RA_BITMASK, 0/*Rc*/);
2581
25820.31,6.RT,11.RA,16.RB,21.OE,22.10,31.Rc:XO:::Add Carrying
2583*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2584*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2585*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2586*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2587	ALU_BEGIN(*rA);
2588	ALU_ADD(*rB);
2589	ALU_END(*rT, 1/*CA*/, OE, Rc);
2590	PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2591
25920.31,6.RT,11.RA,16.RB,21.OE,22.8,31.Rc:XO:::Subtract From Carrying
2593*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2594*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2595*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2596*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2597	/* RT <- ~RA + RB + 1 === RT <- RB - RA */
2598	ALU_BEGIN(*rA);
2599	ALU_NOT;
2600	ALU_ADD(*rB);
2601	ALU_ADD(1);
2602	ALU_END(*rT, 1/*CA*/, OE, Rc);
2603	PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2604
26050.31,6.RT,11.RA,16.RB,21.OE,22.138,31.Rc:XO:::Add Extended
2606*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2607*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2608*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2609*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2610	ALU_BEGIN(*rA);
2611	ALU_ADD(*rB);
2612	ALU_ADD_CA;
2613	ALU_END(*rT, 1/*CA*/, OE, Rc);
2614	PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2615
26160.31,6.RT,11.RA,16.RB,21.OE,22.136,31.Rc:XO:::Subtract From Extended
2617*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2618*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2619*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2620*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2621	ALU_BEGIN(*rA);
2622	ALU_NOT;
2623	ALU_ADD(*rB);
2624	ALU_ADD_CA;
2625	ALU_END(*rT, 1/*CA*/, OE, Rc);
2626	PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2627
26280.31,6.RT,11.RA,16./,21.OE,22.234,31.Rc:XO:::Add to Minus One Extended
2629*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2630*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2631*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2632*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2633	ALU_BEGIN(*rA);
2634	ALU_ADD_CA;
2635	ALU_ADD(-1);
2636	ALU_END(*rT, 1/*CA*/, OE, Rc);
2637	PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2638
26390.31,6.RT,11.RA,16./,21.OE,22.232,31.Rc:XO:::Subtract From Minus One Extended
2640*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2641*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2642*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2643*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2644	ALU_BEGIN(*rA);
2645	ALU_NOT;
2646	ALU_ADD_CA;
2647	ALU_ADD(-1);
2648	ALU_END(*rT, 1/*CA*/, OE, Rc);
2649	PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2650
26510.31,6.RT,11.RA,16./,21.OE,22.202,31.Rc:XO::addze:Add to Zero Extended
2652*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2653*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2654*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2655*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2656	ALU_BEGIN(*rA);
2657	ALU_ADD_CA;
2658	ALU_END(*rT, 1/*CA*/, OE, Rc);
2659	PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2660
26610.31,6.RT,11.RA,16./,21.OE,22.200,31.Rc:XO:::Subtract from Zero Extended
2662*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2663*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2664*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2665*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2666	ALU_BEGIN(*rA);
2667	ALU_NOT;
2668	ALU_ADD_CA;
2669	ALU_END(*rT, 1/*CA*/, OE, Rc);
2670	PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2671
26720.31,6.RT,11.RA,16./,21.OE,22.104,31.Rc:XO:::Negate
2673*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2674*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2675*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2676*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2677	ALU_BEGIN(*rA);
2678	ALU_NOT;
2679	ALU_ADD(1);
2680	ALU_END(*rT,0/*CA*/,OE,Rc);
2681	PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2682
26830.7,6.RT,11.RA,16.SI:D::mulli:Multiply Low Immediate
2684*601: PPC_UNIT_IU,    PPC_UNIT_IU,    5,  5,  0
2685*603: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
2686*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
2687*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  3,  3,  0
2688	signed_word prod = *rA * EXTS(SI);
2689	*rT = prod;
2690	PPC_INSN_INT(RT_BITMASK, RA_BITMASK, 0/*Rc*/);
2691
26920.31,6.RT,11.RA,16.RB,21.OE,22.233,31.Rc:D:64::Multiply Low Doubleword
2693
26940.31,6.RT,11.RA,16.RB,21.OE,22.235,31.Rc:XO::mullw:Multiply Low Word
2695*601: PPC_UNIT_IU,    PPC_UNIT_IU,    5,  5,  0
2696*603: PPC_UNIT_IU,    PPC_UNIT_IU,    5,  5,  0
2697*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    5,  5,  0
2698*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  4,  4,  0
2699	signed64 a = (signed32)(*rA);
2700	signed64 b = (signed32)(*rB);
2701	signed64 prod = a * b;
2702	signed_word t = prod;
2703	*rT = *rA * *rB;
2704	if (t != prod && OE)
2705	  XER |= (xer_overflow | xer_summary_overflow);
2706	CR0_COMPARE(t, 0, Rc);
2707	PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2708
27090.31,6.RT,11.RA,16.RB,21./,22.73,31.Rc:XO:64::Multiply High Doubleword
2710
27110.31,6.RT,11.RA,16.RB,21./,22.75,31.Rc:XO::mulhw:Multiply High Word
2712*601: PPC_UNIT_IU,    PPC_UNIT_IU,    5,  5,  0
2713*603: PPC_UNIT_IU,    PPC_UNIT_IU,    5,  5,  0
2714*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    5,  5,  0
2715*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  4,  4,  0
2716	signed64 a = (signed32)(*rA);
2717	signed64 b = (signed32)(*rB);
2718	signed64 prod = a * b;
2719	signed_word t = EXTRACTED64(prod, 0, 31);
2720	*rT = t;
2721	CR0_COMPARE(t, 0, Rc);
2722	PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2723
27240.31,6.RT,11.RA,16.RB,21./,22.9,31.Rc:XO:64::Multiply High Doubleword Unsigned
2725
27260.31,6.RT,11.RA,16.RB,21./,22.11,31.Rc:XO::mulhwu:Multiply High Word Unsigned
2727*601: PPC_UNIT_IU,    PPC_UNIT_IU,    10, 10, 0
2728*603: PPC_UNIT_IU,    PPC_UNIT_IU,    6,  6,  0
2729*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    6,  6,  0
2730*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  4,  4,  0
2731	unsigned64 a = (unsigned32)(*rA);
2732	unsigned64 b = (unsigned32)(*rB);
2733	unsigned64 prod = a * b;
2734	signed_word t = EXTRACTED64(prod, 0, 31);
2735	*rT = t;
2736	CR0_COMPARE(t, 0, Rc);
2737	PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2738
27390.31,6.RT,11.RA,16.RB,21.OE,22.489,31.Rc:XO:64::Divide Doubleword
2740
27410.31,6.RT,11.RA,16.RB,21.OE,22.491,31.Rc:XO::divw:Divide Word
2742*601: PPC_UNIT_IU,    PPC_UNIT_IU,    36, 36, 0
2743*603: PPC_UNIT_IU,    PPC_UNIT_IU,    37, 37, 0
2744*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    37, 37, 0
2745*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  20, 20, 0
2746	signed64 dividend = (signed32)(*rA);
2747	signed64 divisor = (signed32)(*rB);
2748	if (divisor == 0 /* nb 0x8000..0 is sign extended */
2749	    || (dividend == 0x80000000 && divisor == -1)) {
2750	  if (OE)
2751	    XER |= (xer_overflow | xer_summary_overflow);
2752	  CR0_COMPARE(0, 0, Rc);
2753	}
2754	else {
2755	  signed64 quotent = dividend / divisor;
2756	  *rT = quotent;
2757	  CR0_COMPARE((signed_word)quotent, 0, Rc);
2758	}
2759	PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2760
27610.31,6.RT,11.RA,16.RB,21.OE,22.457,31.Rc:XO:64::Divide Doubleword Unsigned
2762
27630.31,6.RT,11.RA,16.RB,21.OE,22.459,31.Rc:XO::divwu:Divide Word Unsigned
2764*601: PPC_UNIT_IU,    PPC_UNIT_IU,    36, 36, 0
2765*603: PPC_UNIT_IU,    PPC_UNIT_IU,    37, 37, 0
2766*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    37, 37, 0
2767*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  20, 20, 0
2768	unsigned64 dividend = (unsigned32)(*rA);
2769	unsigned64 divisor = (unsigned32)(*rB);
2770	if (divisor == 0) {
2771	  if (OE)
2772	    XER |= (xer_overflow | xer_summary_overflow);
2773	  CR0_COMPARE(0, 0, Rc);
2774	}
2775	else {
2776	  unsigned64 quotent = dividend / divisor;
2777	  *rT = quotent;
2778	  CR0_COMPARE((signed_word)quotent, 0, Rc);
2779	}
2780	PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2781
2782
2783#
2784# I.3.3.10 Fixed-Point Compare Instructions
2785#
2786
27870.11,6.BF,9./,10.L,11.RA,16.SI:D:::Compare Immediate
2788*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2789*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2790*603e:PPC_UNIT_IU,    PPC_UNIT_SRU,   1,  1,  0
2791*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2792	if (!is_64bit_mode && L)
2793	  program_interrupt(processor, cia,
2794	                    illegal_instruction_program_interrupt);
2795	else {
2796	  signed_word a;
2797	  signed_word b = EXTS(SI);
2798	  if (L == 0)
2799	    a = EXTENDED(*rA);
2800	  else
2801	    a = *rA;
2802	  CR_COMPARE(BF, a, b);
2803	}
2804	PPC_INSN_INT_CR(0, RA_BITMASK, BF_BITMASK);
2805
28060.31,6.BF,9./,10.L,11.RA,16.RB,21.0,31./:X:::Compare
2807*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2808*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2809*603e:PPC_UNIT_IU,    PPC_UNIT_SRU,   1,  1,  0
2810*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2811	if (!is_64bit_mode && L)
2812	  program_interrupt(processor, cia,
2813	                    illegal_instruction_program_interrupt);
2814	else {
2815	  signed_word a;
2816	  signed_word b;
2817	  if (L == 0) {
2818	    a = EXTENDED(*rA);
2819	    b = EXTENDED(*rB);
2820	  }
2821	  else {
2822	    a = *rA;
2823	    b = *rB;
2824	  }
2825	  CR_COMPARE(BF, a, b);
2826	}
2827	PPC_INSN_INT_CR(0, RA_BITMASK | RB_BITMASK, BF_BITMASK);
2828
28290.10,6.BF,9./,10.L,11.RA,16.UI:D:::Compare Logical Immediate
2830*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2831*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2832*603e:PPC_UNIT_IU,    PPC_UNIT_SRU,   1,  1,  0
2833*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2834	if (!is_64bit_mode && L)
2835	  program_interrupt(processor, cia,
2836	                    illegal_instruction_program_interrupt);
2837	else {
2838	  unsigned_word a;
2839	  unsigned_word b = UI;
2840	  if (L == 0)
2841	    a = MASKED(*rA, 32, 63);
2842	  else
2843	    a = *rA;
2844	  CR_COMPARE(BF, a, b);
2845	}
2846	PPC_INSN_INT_CR(0, RA_BITMASK, BF_BITMASK);
2847
28480.31,6.BF,9./,10.L,11.RA,16.RB,21.32,31./:X:::Compare Logical
2849*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2850*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2851*603e:PPC_UNIT_IU,    PPC_UNIT_SRU,   1,  1,  0
2852*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2853	if (!is_64bit_mode && L)
2854	  program_interrupt(processor, cia,
2855	                    illegal_instruction_program_interrupt);
2856	else {
2857	  unsigned_word a;
2858	  unsigned_word b;
2859	  if (L == 0) {
2860	    a = MASKED(*rA, 32, 63);
2861	    b = MASKED(*rB, 32, 63);
2862	  }
2863	  else {
2864	    a = *rA;
2865	    b = *rB;
2866	  }
2867	  CR_COMPARE(BF, a, b);
2868	}
2869	PPC_INSN_INT_CR(0, RA_BITMASK | RB_BITMASK, BF_BITMASK);
2870
2871
2872#
2873# I.3.3.11 Fixed-Point Trap Instructions
2874#
2875
28760.2,6.TO,11.RA,16.SI:D:64::Trap Doubleword Immediate
2877	if (!is_64bit_mode)
2878	  program_interrupt(processor, cia,
2879	                    illegal_instruction_program_interrupt);
2880	else {
2881	  signed_word a = *rA;
2882	  signed_word b = EXTS(SI);
2883	  if ((a < b && TO{0})
2884	      || (a > b && TO{1})
2885	      || (a == b && TO{2})
2886	      || ((unsigned_word)a < (unsigned_word)b && TO{3})
2887	      || ((unsigned_word)a > (unsigned_word)b && TO{4})
2888	      )
2889	    program_interrupt(processor, cia,
2890	                      trap_program_interrupt);
2891	}
2892
28930.3,6.TO,11.RA,16.SI:D:::Trap Word Immediate
2894*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2895*603: PPC_UNIT_IU,    PPC_UNIT_IU,    2,  2,  0
2896*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    2,  2,  0
2897*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2898	signed_word a = EXTENDED(*rA);
2899	signed_word b = EXTS(SI);
2900	if ((a < b && TO{0})
2901	    || (a > b && TO{1})
2902	    || (a == b && TO{2})
2903	    || ((unsigned_word)a < (unsigned_word)b && TO{3})
2904	    || ((unsigned_word)a > (unsigned_word)b && TO{4})
2905	    )
2906	  program_interrupt(processor, cia,
2907	                    trap_program_interrupt);
2908
29090.31,6.TO,11.RA,16.RB,21.68,31./:X:64::Trap Doubleword
2910	if (!is_64bit_mode)
2911	  program_interrupt(processor, cia,
2912	                    illegal_instruction_program_interrupt);
2913	else {
2914	  signed_word a = *rA;
2915	  signed_word b = *rB;
2916	  if ((a < b && TO{0})
2917	      || (a > b && TO{1})
2918	      || (a == b && TO{2})
2919	      || ((unsigned_word)a < (unsigned_word)b && TO{3})
2920	      || ((unsigned_word)a > (unsigned_word)b && TO{4})
2921	      )
2922	    program_interrupt(processor, cia,
2923	                      trap_program_interrupt);
2924	}
2925
29260.31,6.TO,11.RA,16.RB,21.4,31./:X:::Trap Word
2927*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2928*603: PPC_UNIT_IU,    PPC_UNIT_IU,    2,  2,  0
2929*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    2,  2,  0
2930*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2931	signed_word a = EXTENDED(*rA);
2932	signed_word b = EXTENDED(*rB);
2933	if (TO == 12 && rA == rB) {
2934	  ITRACE(trace_breakpoint, ("breakpoint\n"));
2935	  cpu_halt(processor, cia, was_trap, 0);
2936	}
2937	else if ((a < b && TO{0})
2938	    || (a > b && TO{1})
2939	    || (a == b && TO{2})
2940	    || ((unsigned_word)a < (unsigned_word)b && TO{3})
2941	    || ((unsigned_word)a > (unsigned_word)b && TO{4})
2942	    )
2943	  program_interrupt(processor, cia,
2944	                    trap_program_interrupt);
2945
2946#
2947# I.3.3.12 Fixed-Point Logical Instructions
2948#
2949
29500.28,6.RS,11.RA,16.UI:D:::AND Immediate
2951*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2952*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2953*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2954*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2955	*rA = *rS & UI;
2956	CR0_COMPARE(*rA, 0, 1/*Rc*/);
2957	ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2958	PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 1/*Rc*/);
2959
29600.29,6.RS,11.RA,16.UI:D:::AND Immediate Shifted
2961*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2962*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2963*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2964*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2965	*rA = *rS & (UI << 16);
2966	CR0_COMPARE(*rA, 0, 1/*Rc*/);
2967	ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2968	PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 1/*Rc*/);
2969
29700.24,6.RS,11.RA,16.UI:D:::OR Immediate
2971*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2972*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2973*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2974*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2975	*rA = *rS | UI;
2976	ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2977	PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 0/*Rc*/);
2978
29790.25,6.RS,11.RA,16.UI:D:::OR Immediate Shifted
2980*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2981*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2982*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2983*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2984	*rA = *rS | (UI << 16);
2985	ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2986	PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 0/*Rc*/);
2987
29880.26,6.RS,11.RA,16.UI:D:::XOR Immediate
2989*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2990*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2991*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2992*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2993	*rA = *rS ^ UI;
2994	ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2995	PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 0/*Rc*/);
2996
29970.27,6.RS,11.RA,16.UI:D:::XOR Immediate Shifted
2998*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2999*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3000*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3001*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
3002	*rA = *rS ^ (UI << 16);
3003	ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3004	PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 0/*Rc*/);
3005
30060.31,6.RS,11.RA,16.RB,21.28,31.Rc:X:::AND
3007*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3008*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3009*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3010*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
3011	*rA = *rS & *rB;
3012	CR0_COMPARE(*rA, 0, Rc);
3013	ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3014	PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
3015
30160.31,6.RS,11.RA,16.RB,21.444,31.Rc:X:::OR
3017*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3018*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3019*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3020*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
3021	*rA = *rS | *rB;
3022	CR0_COMPARE(*rA, 0, Rc);
3023	ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3024	PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
3025
30260.31,6.RS,11.RA,16.RB,21.316,31.Rc:X:::XOR
3027*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3028*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3029*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3030*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
3031	*rA = *rS ^ *rB;
3032	CR0_COMPARE(*rA, 0, Rc);
3033	ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3034	PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
3035
30360.31,6.RS,11.RA,16.RB,21.476,31.Rc:X:::NAND
3037*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3038*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3039*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3040*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
3041	*rA = ~(*rS & *rB);
3042	CR0_COMPARE(*rA, 0, Rc);
3043	ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3044	PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
3045
30460.31,6.RS,11.RA,16.RB,21.124,31.Rc:X:::NOR
3047*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3048*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3049*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3050*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
3051	*rA = ~(*rS | *rB);
3052	CR0_COMPARE(*rA, 0, Rc);
3053	ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3054	PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
3055
30560.31,6.RS,11.RA,16.RB,21.284,31.Rc:X:::Equivalent
3057*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3058*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3059*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3060*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
3061	*rA = ~(*rS ^ *rB); /* A === B */
3062	CR0_COMPARE(*rA, 0, Rc);
3063	ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3064	PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
3065
30660.31,6.RS,11.RA,16.RB,21.60,31.Rc:X:::AND with Complement
3067*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3068*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3069*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3070*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
3071	*rA = *rS & ~*rB;
3072	CR0_COMPARE(*rA, 0, Rc);
3073	ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3074	PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
3075
30760.31,6.RS,11.RA,16.RB,21.412,31.Rc:X:::OR with Complement
3077*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3078*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3079*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3080*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
3081	*rA = *rS | ~*rB;
3082	CR0_COMPARE(*rA, 0, Rc);
3083	ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3084	PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
3085
30860.31,6.RS,11.RA,16./,21.954,31.Rc:X::extsb:Extend Sign Byte
3087*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3088*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3089*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3090*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
3091	*rA = (signed_word)(signed8)*rS;
3092	CR0_COMPARE(*rA, 0, Rc);
3093	ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3094	PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3095
30960.31,6.RS,11.RA,16./,21.922,31.Rc:X::extsh:Extend Sign Half Word
3097*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3098*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3099*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3100*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
3101	*rA = (signed_word)(signed16)*rS;
3102	CR0_COMPARE(*rA, 0, Rc);
3103	ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3104	PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3105
31060.31,6.RS,11.RA,16./,21.986,31.Rc:X:64::Extend Sign Word
3107*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3108*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3109*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3110*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
3111#	*rA = (signed_word)(signed32)*rS;
3112#	CR0_COMPARE(*rA, 0, Rc);
3113
31140.31,6.RS,11.RA,16./,21.58,31.Rc:X:64::Count Leading Zeros Doubleword
3115#	int count = 0;
3116#	unsigned64 mask = BIT64(0);
3117#	unsigned64 source = *rS;
3118#	while (!(source & mask) && mask != 0) {
3119#	  mask >>= 1;
3120#	  count++;
3121#	}
3122#	*rA = count;
3123#	CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */
3124
31250.31,6.RS,11.RA,16./,21.26,31.Rc:X:::Count Leading Zeros Word
3126*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3127*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3128*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3129*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
3130	int count = 0;
3131	unsigned32 mask = BIT32(0);
3132	unsigned32 source = *rS;
3133	while (!(source & mask) && mask != 0) {
3134	  mask >>= 1;
3135	  count++;
3136	}
3137	*rA = count;
3138	ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3139	CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */
3140
3141
3142#
3143# I.3.3.13 Fixed-Point Rotate and Shift Instructions
3144#
3145
31460.30,6.RS,11.RA,16.sh_0_4,21.mb,27.0,30.sh_5,31.Rc:MD:64::Rotate Left Doubleword Immediate then Clear Left
3147#	long n = (sh_5 << 4) | sh_0_4;
3148#	unsigned_word r = ROTL64(*rS, n);
3149#	long b = (mb_5 << 4) | mb_0_4;
3150#	unsigned_word m = MASK(b, 63);
3151#	signed_word result = r & m;
3152#	*rA = result;
3153#	ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3154#	CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
3155
31560.30,6.RS,11.RA,16.sh_0_4,21.me,27.1,30.sh_5,31.Rc:MD:64::Rotate Left Doubleword Immediate then Clear Right
3157#	long n = (sh_5 << 4) | sh_0_4;
3158#	unsigned_word r = ROTL64(*rS, n);
3159#	long e = (me_5 << 4) | me_0_4;
3160#	unsigned_word m = MASK(0, e);
3161#	signed_word result = r & m;
3162#	*rA = result;
3163#	CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
3164
31650.30,6.RS,11.RA,16.sh_0_4,21.mb,27.2,30.sh_5,31.Rc:MD:64::Rotate Left Doubleword Immediate then Clear
3166#	long n = (sh_5 << 4) | sh_0_4;
3167#	unsigned_word r = ROTL64(*rS, n);
3168#	long b = (mb_5 << 4) | mb_0_4;
3169#	unsigned_word m = MASK(0, (64-n));
3170#	signed_word result = r & m;
3171#	*rA = result;
3172#	CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
3173
31740.21,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M:::Rotate Left Word Immediate then AND with Mask
3175*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3176*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3177*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3178*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
3179	long n = SH;
3180	unsigned32 s = *rS;
3181	unsigned32 r = ROTL32(s, n);
3182	unsigned32 m = MASK(MB+32, ME+32);
3183	signed_word result = r & m;
3184	*rA = result;
3185	CR0_COMPARE(result, 0, Rc);
3186	ITRACE(trace_alu,
3187	       ("n=%ld, s=0x%lx, r=0x%lx, m=0x%lx, result=0x%lx, cr=0x%lx\n",
3188	        n, (unsigned long)s, (unsigned long)r, (unsigned long)m,
3189		(unsigned long)result, (unsigned long)CR));
3190	PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3191
31920.30,6.RS,11.RA,16.RB,21.mb,27.8,31.Rc:MDS:64::Rotate Left Doubleword then Clear Left
3193#	long n = MASKED(*rB, 58, 63);
3194#	unsigned_word r = ROTL64(*rS, n);
3195#	long b = (mb_5 << 4) | mb_0_4;
3196#	unsigned_word m = MASK(b, 63);
3197#	signed_word result = r & m;
3198#	*rA = result;
3199#	CR0_COMPARE(result, 0, Rc);
3200
32010.30,6.RS,11.RA,16.RB,21.me,27.9,31.Rc:MDS:64::Rotate Left Doubleword then Clear Right
3202#	long n = MASKED(*rB, 58, 63);
3203#	unsigned_word r = ROTL64(*rS, n);
3204#	long e = (me_5 << 4) | me_0_4;
3205#	unsigned_word m = MASK(0, e);
3206#	signed_word result = r & m;
3207#	*rA = result;
3208#	CR0_COMPARE(result, 0, Rc);
3209
32100.23,6.RS,11.RA,16.RB,21.MB,26.ME,31.Rc:M:::Rotate Left Word then AND with Mask
3211	long n = MASKED(*rB, 59, 63);
3212	unsigned32 r = ROTL32(*rS, n);
3213	unsigned32 m = MASK(MB+32, ME+32);
3214	signed_word result = r & m;
3215	*rA = result;
3216	CR0_COMPARE(result, 0, Rc);
3217
32180.30,6.RS,11.RA,16.sh_0_4,21.mb,27.3,30.sh_5,31.Rc:MD:64::Rotate Left Doubleword Immediate then Mask Insert
3219#	long n = (sh_5 << 4) | sh_0_4;
3220#	unsigned_word r = ROTL64(*rS, n);
3221#	long b = (mb_5 << 4) | mb_0_4;
3222#	unsigned_word m = MASK(b, (64-n));
3223#	signed_word result = (r & m) | (*rA & ~m)
3224#	*rA = result;
3225#	CR0_COMPARE(result, 0, Rc);
3226
32270.20,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M::rlwimi:Rotate Left Word Immediate then Mask Insert
3228*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3229*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3230*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3231*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
3232	long n = SH;
3233	unsigned32 r = ROTL32(*rS, n);
3234	unsigned32 m = MASK(MB+32, ME+32);
3235	signed_word result = (r & m) | (*rA & ~m);
3236	*rA = result;
3237	ITRACE(trace_alu, (": n=%ld *rS=0x%lx r=0x%lx m=0x%lx result=0x%lx\n",
3238	                   n, (unsigned long)*rS, (unsigned long)r, (unsigned long)m,
3239			   (unsigned long)result));
3240	CR0_COMPARE(result, 0, Rc);
3241	PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3242
3243
32440.31,6.RS,11.RA,16.RB,21.27,31.Rc:X:64::Shift Left Doubleword
3245
32460.31,6.RS,11.RA,16.RB,21.24,31.Rc:X:::Shift Left Word
3247*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3248*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3249*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3250*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
3251	int n = MASKED(*rB, 58, 63);
3252	unsigned32 source = *rS;
3253	signed_word shifted;
3254	if (n < 32)
3255	  shifted = (source << n);
3256	else
3257	  shifted = 0;
3258	*rA = shifted;
3259	CR0_COMPARE(shifted, 0, Rc);
3260	ITRACE(trace_alu,
3261	       ("n=%d, source=0x%lx, shifted=0x%lx\n",
3262	        n, (unsigned long)source, (unsigned long)shifted));
3263	PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3264
32650.31,6.RS,11.RA,16.RB,21.539,31.Rc:X:64::Shift Right Doubleword
3266
32670.31,6.RS,11.RA,16.RB,21.536,31.Rc:X:::Shift Right Word
3268*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3269*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3270*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3271*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
3272	int n = MASKED(*rB, 58, 63);
3273	unsigned32 source = *rS;
3274	signed_word shifted;
3275	if (n < 32)
3276	  shifted = (source >> n);
3277	else
3278	  shifted = 0;
3279	*rA = shifted;
3280	CR0_COMPARE(shifted, 0, Rc);
3281	ITRACE(trace_alu, \
3282	       ("n=%d, source=0x%lx, shifted=0x%lx\n",
3283	        n, (unsigned long)source, (unsigned long)shifted));
3284	PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3285
32860.31,6.RS,11.RA,16.sh_0_4,21.413,30.sh_5,31.Rc:XS:64::Shift Right Algebraic Doubleword Immediate
3287
32880.31,6.RS,11.RA,16.SH,21.824,31.Rc:X:::Shift Right Algebraic Word Immediate
3289*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3290*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3291*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3292*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
3293	int n = SH;
3294	signed_word r = ROTL32(*rS, /*64*/32-n);
3295	signed_word m = MASK(n+32, 63);
3296	int S = MASKED(*rS, 32, 32);
3297	signed_word shifted = (r & m) | (S ? ~m : 0);
3298	*rA = shifted;
3299	if (S && ((r & ~m) & MASK(32, 63)) != 0)
3300	  XER |= xer_carry;
3301	else
3302	  XER &= ~xer_carry;
3303	CR0_COMPARE(shifted, 0, Rc);
3304	ITRACE(trace_alu, (" Result = %ld (0x%lx), XER = %ld\n",
3305			   (long)*rA, (long)*rA, (long)XER));
3306	PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3307
33080.31,6.RS,11.RA,16.RB,21.794,31.Rc:X:64::Shift Right Algebraic Doubleword
3309
33100.31,6.RS,11.RA,16.RB,21.792,31.Rc:X:::Shift Right Algebraic Word
3311*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3312*603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3313*603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3314*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
3315	unsigned64 mask;
3316	int n = MASKED(*rB, 59, 63);
3317	signed32 source = (signed32)*rS; /* signed to keep sign bit */
3318	signed32 shifted = source >> n;
3319	int S = (MASKED(*rS,32,32) != 0);
3320	signed64 r = ((unsigned64) source);
3321	r = ((unsigned64) source) << 32 | (unsigned32) source;
3322	r = ROTL64(r,64-n);
3323	if (MASKED(*rB,58,58) == 0)
3324		mask = (unsigned64) MASK64(n+32,63);
3325	else
3326		mask = (unsigned64) 0;
3327	*rA = (signed_word) (r & mask | ((signed64) -1*S) & ~mask); /* if 64bit will sign extend */
3328	if (S && (MASKED(r & ~mask,32,63)!=0))
3329	  XER |= xer_carry;
3330	else
3331	  XER &= ~xer_carry;
3332	CR0_COMPARE(*rA, 0, Rc);
3333	ITRACE(trace_alu, (" Result = %ld (0x%lx), XER = %ld\n",
3334			   (long)*rA, (long)*rA, (long)XER));
3335	PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3336
3337#
3338# I.3.3.14 Move to/from System Register Instructions
3339#
3340
33410.31,6.RS,11.SPR,21.467,31./:XFX::mtspr %SPR, %RS:Move to Special Purpose Register
3342*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3343*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   2,  2,  0
3344*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   2,  2,  0
3345*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  1,  1,  0
3346	int n = (SPR{5:9} << 5) | SPR{0:4};
3347	if (SPR{0} && IS_PROBLEM_STATE(processor))
3348	  program_interrupt(processor, cia,
3349	                    privileged_instruction_program_interrupt);
3350	else if (!spr_is_valid(n)
3351	         || spr_is_readonly(n))
3352	  program_interrupt(processor, cia,
3353	                    illegal_instruction_program_interrupt);
3354	else {
3355	  spreg new_val = (spr_length(n) == 64
3356			   ? *rS
3357			   : MASKED(*rS, 32, 63));
3358	  /* HACK - time base registers need to be updated immediatly */
3359	  if (WITH_TIME_BASE) {
3360	    switch (n) {
3361	    case spr_tbu:
3362	      cpu_set_time_base(processor,
3363	                        (MASKED64(cpu_get_time_base(processor), 32, 63)
3364	                         | INSERTED64(new_val, 0, 31)));
3365	      break;
3366	    case spr_tbl:
3367	      cpu_set_time_base(processor,
3368	                        (MASKED64(cpu_get_time_base(processor), 0, 31)
3369	                         | INSERTED64(new_val, 32, 63)));
3370	      break;
3371	    case spr_dec:
3372	      cpu_set_decrementer(processor, new_val);
3373	      break;
3374	    default:
3375	      SPREG(n) = new_val;
3376	      break;
3377	    }
3378	  }
3379	  else {
3380	    SPREG(n) = new_val;
3381	  }
3382	}
3383	PPC_INSN_TO_SPR(RS_BITMASK, n);
3384
33850.31,6.RT,11.SPR,21.339,31./:XFX::mfspr %RT, %SPR:Move from Special Purpose Register
3386*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3387*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
3388*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
3389*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  3,  3,  0
3390	int n = (SPR{5:9} << 5) | SPR{0:4};
3391	if (SPR{0} && IS_PROBLEM_STATE(processor))
3392	  program_interrupt(processor, cia,
3393	                    privileged_instruction_program_interrupt);
3394	else if (!spr_is_valid(n))
3395	  program_interrupt(processor, cia,
3396	                    illegal_instruction_program_interrupt);
3397	else {
3398	  /* HACK - time base registers need to be calculated */
3399	  if (WITH_TIME_BASE) {
3400	    switch (n) {
3401	    case spr_dec:
3402	      *rT = cpu_get_decrementer(processor);
3403	      break;
3404		case spr_tbrl:
3405	  	  if (is_64bit_implementation) *rT = TB;
3406	  	  else                         *rT = EXTRACTED64(TB, 32, 63);
3407		break;
3408		case spr_tbru:
3409	  	  if (is_64bit_implementation) *rT = EXTRACTED64(TB, 0, 31);
3410		  else                         *rT = EXTRACTED64(TB, 0, 31);
3411		break;
3412	    case spr_tbu:
3413	    case spr_tbl:
3414	      /* NOTE - these SPR's are not readable. Use mftb[ul] */
3415	    default:
3416	      *rT = SPREG(n);
3417	      break;
3418	    }
3419	  }
3420	  else {
3421	    *rT = SPREG(n);
3422	  }
3423	}
3424	PPC_INSN_FROM_SPR(RT_BITMASK, n);
3425
34260.31,6.RS,11./,12.FXM,20./,21.144,31./:XFX::mtfcr:Move to Condition Register Fields
3427*601: PPC_UNIT_IU,    PPC_UNIT_IU,    2,  2,  0
3428*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
3429*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
3430*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  1,  1,  0
3431	if (FXM == 0xff) {
3432	  CR = *rS;
3433	}
3434	else {
3435	  unsigned_word mask = 0;
3436	  unsigned_word f;
3437	  for (f = 0; f < 8; f++) {
3438	    if (FXM & (0x80 >> f))
3439	      mask |= (0xf << 4*(7-f));
3440	  }
3441	  CR = (MASKED(*rS, 32, 63) & mask) | (CR & ~mask);
3442	}
3443	PPC_INSN_MTCR(RS_BITMASK, FXM);
3444
34450.31,6.BF,9./,11./,16./,21.512,31./:X:::Move to Condition Register from XER
3446#	CR_SET(BF, EXTRACTED32(XER, 0, 3));
3447#	MBLIT32(XER, 0, 3, 0);
3448
34490.31,6.RT,11./,16./,21.19,31./:X:::Move From Condition Register
3450*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3451*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
3452*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
3453*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  3,  3,  0
3454	*rT = (unsigned32)CR;
3455	PPC_INSN_MFCR(RT_BITMASK);
3456
3457#
3458# I.4.6.2 Floating-Point Load Instructions
3459#
3460
34610.48,6.FRT,11.RA,16.D:D:f:lfs:Load Floating-Point Single
3462*601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
3463*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3464*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3465*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3466	unsigned_word b;
3467	unsigned_word EA;
3468	if (RA_is_0) b = 0;
3469	else         b = *rA;
3470	EA = b + EXTS(D);
3471	*frT = DOUBLE(MEM(unsigned, EA, 4));
3472	PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3473
34740.31,6.FRT,11.RA,16.RB,21.535,31./:X:f::Load Floating-Point Single Indexed
3475*601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
3476*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3477*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3478*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3479	unsigned_word b;
3480	unsigned_word EA;
3481	if (RA_is_0) b = 0;
3482	else         b = *rA;
3483	EA = b + *rB;
3484	*frT = DOUBLE(MEM(unsigned, EA, 4));
3485	PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3486
34870.49,6.FRT,11.RA,16.D:D:f::Load Floating-Point Single with Update
3488*601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
3489*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3490*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3491*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3492	unsigned_word EA;
3493	if (RA_is_0)
3494	  program_interrupt(processor, cia,
3495	                    illegal_instruction_program_interrupt);
3496	EA = *rA + EXTS(D);
3497	*frT = DOUBLE(MEM(unsigned, EA, 4));
3498	*rA = EA;
3499	PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3500
35010.31,6.FRT,11.RA,16.RB,21.567,31./:X:f::Load Floating-Point Single with Update Indexed
3502*601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
3503*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3504*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3505*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3506	unsigned_word EA;
3507	if (RA_is_0)
3508	  program_interrupt(processor, cia,
3509	                    illegal_instruction_program_interrupt);
3510	EA = *rA + *rB;
3511	*frT = DOUBLE(MEM(unsigned, EA, 4));
3512	*rA = EA;
3513	PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3514
35150.50,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double
3516*601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
3517*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3518*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3519*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3520	unsigned_word b;
3521	unsigned_word EA;
3522	if (RA_is_0) b = 0;
3523	else         b = *rA;
3524	EA = b + EXTS(D);
3525	*frT = MEM(unsigned, EA, 8);
3526	PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3527
35280.31,6.FRT,11.RA,16.RB,21.599,31./:X:f::Load Floating-Point Double Indexed
3529*601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
3530*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3531*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3532*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3533	unsigned_word b;
3534	unsigned_word EA;
3535	if (RA_is_0) b = 0;
3536	else         b = *rA;
3537	EA = b + *rB;
3538	*frT = MEM(unsigned, EA, 8);
3539	PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3540
35410.51,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double with Update
3542*601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
3543*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3544*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3545*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3546	unsigned_word EA;
3547	if (RA_is_0)
3548	  program_interrupt(processor, cia,
3549	                    illegal_instruction_program_interrupt);
3550	EA = *rA + EXTS(D);
3551	*frT = MEM(unsigned, EA, 8);
3552	*rA = EA;
3553	PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3554
35550.31,6.FRT,11.RA,16.RB,21.631,31./:X:f::Load Floating-Point Double with Update Indexed
3556*601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
3557*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3558*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3559*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3560	unsigned_word EA;
3561	if (RA_is_0)
3562	  program_interrupt(processor, cia,
3563	                    illegal_instruction_program_interrupt);
3564	EA = *rA + *rB;
3565	*frT = MEM(unsigned, EA, 8);
3566	*rA = EA;
3567	PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3568
3569
3570#
3571# I.4.6.3 Floating-Point Store Instructions
3572#
3573
35740.52,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single
3575*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3576*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3577*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3578*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3579	unsigned_word b;
3580	unsigned_word EA;
3581	if (RA_is_0) b = 0;
3582	else         b = *rA;
3583	EA = b + EXTS(D);
3584	STORE(EA, 4, SINGLE(*frS));
3585	PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3586
35870.31,6.FRS,11.RA,16.RB,21.663,31./:X:f::Store Floating-Point Single Indexed
3588*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3589*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3590*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3591*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3592	unsigned_word b;
3593	unsigned_word EA;
3594	if (RA_is_0) b = 0;
3595	else         b = *rA;
3596	EA = b + *rB;
3597	STORE(EA, 4, SINGLE(*frS));
3598	PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3599
36000.53,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single with Update
3601*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3602*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3603*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3604*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3605	unsigned_word EA;
3606	if (RA_is_0)
3607	  program_interrupt(processor, cia,
3608	                    illegal_instruction_program_interrupt);
3609	EA = *rA + EXTS(D);
3610	STORE(EA, 4, SINGLE(*frS));
3611	*rA = EA;
3612	PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3613
36140.31,6.FRS,11.RA,16.RB,21.695,31./:X:f::Store Floating-Point Single with Update Indexed
3615*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3616*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3617*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3618*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3619	unsigned_word EA;
3620	if (RA_is_0)
3621	  program_interrupt(processor, cia,
3622	                    illegal_instruction_program_interrupt);
3623	EA = *rA + *rB;
3624	STORE(EA, 4, SINGLE(*frS));
3625	*rA = EA;
3626	PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3627
36280.54,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double
3629*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3630*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3631*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3632*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3633	unsigned_word b;
3634	unsigned_word EA;
3635	if (RA_is_0) b = 0;
3636	else         b = *rA;
3637	EA = b + EXTS(D);
3638	STORE(EA, 8, *frS);
3639	PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3640
36410.31,6.FRS,11.RA,16.RB,21.727,31./:X:f::Store Floating-Point Double Indexed
3642*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3643*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3644*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3645*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3646	unsigned_word b;
3647	unsigned_word EA;
3648	if (RA_is_0) b = 0;
3649	else         b = *rA;
3650	EA = b + *rB;
3651	STORE(EA, 8, *frS);
3652	PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3653
36540.31,6.FRS,11.RA,16.RB,21.983,31./:X:f::Store Floating-Point Integer Word Indexed
3655*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3656*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3657*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3658	unsigned_word b;
3659	unsigned_word EA;
3660	if (RA_is_0) b = 0;
3661	else         b = *rA;
3662	EA = b + *rB;
3663	STORE(EA, 4, *frS);
3664	PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3665
36660.55,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double with Update
3667*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3668*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3669*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3670*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3671	unsigned_word EA;
3672	if (RA_is_0)
3673	  program_interrupt(processor, cia,
3674	                    illegal_instruction_program_interrupt);
3675	EA = *rA + EXTS(D);
3676	STORE(EA, 8, *frS);
3677	*rA = EA;
3678	PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3679
36800.31,6.FRS,11.RA,16.RB,21.759,31./:X:f::Store Floating-Point Double with Update Indexed
3681*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3682*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3683*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3684*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3685	unsigned_word EA;
3686	if (RA_is_0)
3687	  program_interrupt(processor, cia,
3688	                    illegal_instruction_program_interrupt);
3689	EA = *rA + *rB;
3690	STORE(EA, 8, *frS);
3691	*rA = EA;
3692	PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3693
3694
3695#
3696# I.4.6.4 Floating-Point Move Instructions
3697#
3698
36990.63,6.FRT,11./,16.FRB,21.72,31.Rc:X:f::Floating Move Register
3700*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3701*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3702*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3703*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3704	*frT = *frB;
3705	CR1_UPDATE(Rc);
3706	PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3707
37080.63,6.FRT,11./,16.FRB,21.40,31.Rc:X:f::Floating Negate
3709*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3710*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3711*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3712*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3713	*frT = *frB ^ BIT64(0);
3714	CR1_UPDATE(Rc);
3715	PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3716
37170.63,6.FRT,11./,16.FRB,21.264,31.Rc:X:f::Floating Absolute Value
3718*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3719*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3720*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3721*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3722	*frT = *frB & ~BIT64(0);
3723	CR1_UPDATE(Rc);
3724	PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3725
37260.63,6.FRT,11./,16.FRB,21.136,31.Rc:X:f::Floating Negative Absolute Value
3727*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3728*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3729*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3730*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3731	*frT = *frB | BIT64(0);
3732	CR1_UPDATE(Rc);
3733	PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3734
3735
3736#
3737# I.4.6.5 Floating-Point Arithmetic Instructions
3738#
3739
37400.63,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadd:Floating Add
3741*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3742*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3743*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3744*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3745	FPSCR_BEGIN;
3746	if (is_invalid_operation(processor, cia,
3747	                         *frA, *frB,
3748	                         fpscr_vxsnan | fpscr_vxisi,
3749	                         0, /*single?*/
3750	                         0) /*negate?*/) {
3751	  invalid_arithemetic_operation(processor, cia,
3752	                                frT, *frA, *frB, 0,
3753	                                0, /*instruction_is_frsp*/
3754	                                0, /*instruction_is_convert_to_64bit*/
3755	                                0, /*instruction_is_convert_to_32bit*/
3756	                                0); /*single-precision*/
3757	}
3758	else {
3759	  /*HACK!*/
3760	  double s = *(double*)frA + *(double*)frB;
3761	  *(double*)frT = s;
3762	}
3763	FPSCR_END(Rc);
3764	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3765
37660.59,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadds:Floating Add Single
3767*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3768*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3769*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3770*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3771	FPSCR_BEGIN;
3772	if (is_invalid_operation(processor, cia,
3773	                         *frA, *frB,
3774	                         fpscr_vxsnan | fpscr_vxisi,
3775	                         1, /*single?*/
3776	                         0) /*negate?*/) {
3777	  invalid_arithemetic_operation(processor, cia,
3778	                                frT, *frA, *frB, 0,
3779	                                0, /*instruction_is_frsp*/
3780	                                0, /*instruction_is_convert_to_64bit*/
3781	                                0, /*instruction_is_convert_to_32bit*/
3782	                                1); /*single-precision*/
3783	}
3784	else {
3785	  /*HACK!*/
3786	  float s = *(double*)frA + *(double*)frB;
3787	  *(double*)frT = s;
3788	}
3789	FPSCR_END(Rc);
3790	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3791
37920.63,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsub:Floating Subtract
3793*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3794*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3795*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3796*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3797	FPSCR_BEGIN;
3798	if (is_invalid_operation(processor, cia,
3799	                         *frA, *frB,
3800	                         fpscr_vxsnan | fpscr_vxisi,
3801	                         0, /*single?*/
3802	                         1) /*negate?*/) {
3803	  invalid_arithemetic_operation(processor, cia,
3804	                                frT, *frA, *frB, 0,
3805	                                0, /*instruction_is_frsp*/
3806	                                0, /*instruction_is_convert_to_64bit*/
3807	                                0, /*instruction_is_convert_to_32bit*/
3808	                                0); /*single-precision*/
3809	}
3810	else {
3811	  /*HACK!*/
3812	  double s = *(double*)frA - *(double*)frB;
3813	  *(double*)frT = s;
3814	}
3815	FPSCR_END(Rc);
3816	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3817
38180.59,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsubs:Floating Subtract Single
3819*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3820*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3821*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3822*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3823	FPSCR_BEGIN;
3824	if (is_invalid_operation(processor, cia,
3825	                         *frA, *frB,
3826	                         fpscr_vxsnan | fpscr_vxisi,
3827	                         1, /*single?*/
3828	                         1) /*negate?*/) {
3829	  invalid_arithemetic_operation(processor, cia,
3830	                                frT, *frA, *frB, 0,
3831	                                0, /*instruction_is_frsp*/
3832	                                0, /*instruction_is_convert_to_64bit*/
3833	                                0, /*instruction_is_convert_to_32bit*/
3834	                                1); /*single-precision*/
3835	}
3836	else {
3837	  /*HACK!*/
3838	  float s = *(double*)frA - *(double*)frB;
3839	  *(double*)frT = s;
3840	}
3841	FPSCR_END(Rc);
3842	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3843
38440.63,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmul:Floating Multiply
3845*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   5,  5,  0
3846*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
3847*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
3848*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3849	FPSCR_BEGIN;
3850	if (is_invalid_operation(processor, cia,
3851	                         *frA, *frC,
3852	                         fpscr_vxsnan | fpscr_vximz,
3853	                         0, /*single?*/
3854	                         0) /*negate?*/) {
3855	  invalid_arithemetic_operation(processor, cia,
3856	                                frT, *frA, 0, *frC,
3857	                                0, /*instruction_is_frsp*/
3858	                                0, /*instruction_is_convert_to_64bit*/
3859	                                0, /*instruction_is_convert_to_32bit*/
3860	                                0); /*single-precision*/
3861	}
3862	else {
3863	  /*HACK!*/
3864	  double s = *(double*)frA * *(double*)frC;
3865	  *(double*)frT = s;
3866	}
3867	FPSCR_END(Rc);
3868	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRC_BITMASK, Rc);
3869
38700.59,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmuls:Floating Multiply Single
3871*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3872*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3873*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3874*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3875	FPSCR_BEGIN;
3876	if (is_invalid_operation(processor, cia,
3877	                         *frA, *frC,
3878	                         fpscr_vxsnan | fpscr_vximz,
3879	                         1, /*single?*/
3880	                         0) /*negate?*/) {
3881	  invalid_arithemetic_operation(processor, cia,
3882	                                frT, *frA, 0, *frC,
3883	                                0, /*instruction_is_frsp*/
3884	                                0, /*instruction_is_convert_to_64bit*/
3885	                                0, /*instruction_is_convert_to_32bit*/
3886	                                1); /*single-precision*/
3887	}
3888	else {
3889	  /*HACK!*/
3890	  float s = *(double*)frA * *(double*)frC;
3891	  *(double*)frT = s;
3892	}
3893	FPSCR_END(Rc);
3894	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRC_BITMASK, Rc);
3895
38960.63,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdiv:Floating Divide
3897*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   31, 31, 0
3898*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   33, 33, 0
3899*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   33, 33, 0
3900*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   32, 32, 0
3901	FPSCR_BEGIN;
3902	if (is_invalid_operation(processor, cia,
3903	                         *frA, *frB,
3904	                         fpscr_vxsnan | fpscr_vxzdz,
3905	                         0, /*single?*/
3906	                         0) /*negate?*/) {
3907	  invalid_arithemetic_operation(processor, cia,
3908	                                frT, *frA, *frB, 0,
3909	                                0, /*instruction_is_frsp*/
3910	                                0, /*instruction_is_convert_to_64bit*/
3911	                                0, /*instruction_is_convert_to_32bit*/
3912	                                0); /*single-precision*/
3913	}
3914	else if (is_invalid_zero_divide (processor, cia,
3915	                                 *frA, *frB,
3916	                                 0 /*single?*/)) {
3917	  invalid_zero_divide_operation (processor, cia,
3918	                                 frT, *frA, *frB,
3919	                                 0 /*single?*/);
3920	}
3921	else {
3922	  /*HACK!*/
3923	  double s = *(double*)frA / *(double*)frB;
3924	  *(double*)frT = s;
3925	}
3926	FPSCR_END(Rc);
3927	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3928
39290.59,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdivs:Floating Divide Single
3930*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   17, 17, 0
3931*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   18, 18, 0
3932*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   18, 18, 0
3933*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   18, 18, 0
3934	FPSCR_BEGIN;
3935	if (is_invalid_operation(processor, cia,
3936	                         *frA, *frB,
3937	                         fpscr_vxsnan | fpscr_vxzdz,
3938	                         1, /*single?*/
3939	                         0) /*negate?*/) {
3940	  invalid_arithemetic_operation(processor, cia,
3941	                                frT, *frA, *frB, 0,
3942	                                0, /*instruction_is_frsp*/
3943	                                0, /*instruction_is_convert_to_64bit*/
3944	                                0, /*instruction_is_convert_to_32bit*/
3945	                                1); /*single-precision*/
3946	}
3947	else if (is_invalid_zero_divide (processor, cia,
3948	                                 *frA, *frB,
3949	                                 1 /*single?*/)) {
3950	  invalid_zero_divide_operation (processor, cia,
3951	                                 frT, *frA, *frB,
3952	                                 1 /*single?*/);
3953	}
3954	else {
3955	  /*HACK!*/
3956	  float s = *(double*)frA / *(double*)frB;
3957	  *(double*)frT = s;
3958	}
3959	FPSCR_END(Rc);
3960	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3961
39620.63,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f:fmadd:Floating Multiply-Add
3963*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   5,  5,  0
3964*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
3965*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
3966*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3967	FPSCR_BEGIN;
3968	double product; /*HACK! - incorrectly loosing precision ... */
3969	/* compute the multiply */
3970	if (is_invalid_operation(processor, cia,
3971	                         *frA, *frC,
3972	                         fpscr_vxsnan | fpscr_vximz,
3973	                         0, /*single?*/
3974	                         0) /*negate?*/) {
3975	  union { double d; unsigned64 u; } tmp;
3976	  invalid_arithemetic_operation(processor, cia,
3977	                                &tmp.u, *frA, 0, *frC,
3978	                                0, /*instruction_is_frsp*/
3979	                                0, /*instruction_is_convert_to_64bit*/
3980	                                0, /*instruction_is_convert_to_32bit*/
3981	                                0); /*single-precision*/
3982	  product = tmp.d;
3983	}
3984	else {
3985	  /*HACK!*/
3986	  product = *(double*)frA * *(double*)frC;
3987	}
3988	/* compute the add */
3989	if (is_invalid_operation(processor, cia,
3990	                         product, *frB,
3991	                         fpscr_vxsnan | fpscr_vxisi,
3992	                         0, /*single?*/
3993	                         0) /*negate?*/) {
3994	  invalid_arithemetic_operation(processor, cia,
3995	                                frT, product, *frB, 0,
3996	                                0, /*instruction_is_frsp*/
3997	                                0, /*instruction_is_convert_to_64bit*/
3998	                                0, /*instruction_is_convert_to_32bit*/
3999	                                0); /*single-precision*/
4000	}
4001	else {
4002	  /*HACK!*/
4003	  double s = product + *(double*)frB;
4004	  *(double*)frT = s;
4005	}
4006	FPSCR_END(Rc);
4007	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4008
40090.59,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f::Floating Multiply-Add Single
4010*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
4011*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4012*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4013*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4014	FPSCR_BEGIN;
4015	float product; /*HACK! - incorrectly loosing precision ... */
4016	/* compute the multiply */
4017	if (is_invalid_operation(processor, cia,
4018	                         *frA, *frC,
4019	                         fpscr_vxsnan | fpscr_vximz,
4020	                         1, /*single?*/
4021	                         0) /*negate?*/) {
4022	  union { double d; unsigned64 u; } tmp;
4023	  invalid_arithemetic_operation(processor, cia,
4024	                                &tmp.u, *frA, 0, *frC,
4025	                                0, /*instruction_is_frsp*/
4026	                                0, /*instruction_is_convert_to_64bit*/
4027	                                0, /*instruction_is_convert_to_32bit*/
4028	                                0); /*single-precision*/
4029	  product = tmp.d;
4030	}
4031	else {
4032	  /*HACK!*/
4033	  product = *(double*)frA * *(double*)frC;
4034	}
4035	/* compute the add */
4036	if (is_invalid_operation(processor, cia,
4037	                         product, *frB,
4038	                         fpscr_vxsnan | fpscr_vxisi,
4039	                         1, /*single?*/
4040	                         0) /*negate?*/) {
4041	  invalid_arithemetic_operation(processor, cia,
4042	                                frT, product, *frB, 0,
4043	                                0, /*instruction_is_frsp*/
4044	                                0, /*instruction_is_convert_to_64bit*/
4045	                                0, /*instruction_is_convert_to_32bit*/
4046	                                0); /*single-precision*/
4047	}
4048	else {
4049	  /*HACK!*/
4050	  float s = product + *(double*)frB;
4051	  *(double*)frT = (double)s;
4052	}
4053	FPSCR_END(Rc);
4054	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4055
40560.63,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract
4057*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   5,  5,  0
4058*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
4059*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
4060*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4061	FPSCR_BEGIN;
4062	double product; /*HACK! - incorrectly loosing precision ... */
4063	/* compute the multiply */
4064	if (is_invalid_operation(processor, cia,
4065	                         *frA, *frC,
4066	                         fpscr_vxsnan | fpscr_vximz,
4067	                         0, /*single?*/
4068	                         0) /*negate?*/) {
4069	  union { double d; unsigned64 u; } tmp;
4070	  invalid_arithemetic_operation(processor, cia,
4071	                                &tmp.u, *frA, 0, *frC,
4072	                                0, /*instruction_is_frsp*/
4073	                                0, /*instruction_is_convert_to_64bit*/
4074	                                0, /*instruction_is_convert_to_32bit*/
4075	                                0); /*single-precision*/
4076	  product = tmp.d;
4077	}
4078	else {
4079	  /*HACK!*/
4080	  product = *(double*)frA * *(double*)frC;
4081	}
4082	/* compute the subtract */
4083	if (is_invalid_operation(processor, cia,
4084	                         product, *frB,
4085	                         fpscr_vxsnan | fpscr_vxisi,
4086	                         0, /*single?*/
4087	                         0) /*negate?*/) {
4088	  invalid_arithemetic_operation(processor, cia,
4089	                                frT, product, *frB, 0,
4090	                                0, /*instruction_is_frsp*/
4091	                                0, /*instruction_is_convert_to_64bit*/
4092	                                0, /*instruction_is_convert_to_32bit*/
4093	                                0); /*single-precision*/
4094	}
4095	else {
4096	  /*HACK!*/
4097	  double s = product - *(double*)frB;
4098	  *(double*)frT = s;
4099	}
4100	FPSCR_END(Rc);
4101	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4102
41030.59,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract Single
4104*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
4105*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4106*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4107*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4108	FPSCR_BEGIN;
4109	float product; /*HACK! - incorrectly loosing precision ... */
4110	/* compute the multiply */
4111	if (is_invalid_operation(processor, cia,
4112	                         *frA, *frC,
4113	                         fpscr_vxsnan | fpscr_vximz,
4114	                         1, /*single?*/
4115	                         0) /*negate?*/) {
4116	  union { double d; unsigned64 u; } tmp;
4117	  invalid_arithemetic_operation(processor, cia,
4118	                                &tmp.u, *frA, 0, *frC,
4119	                                0, /*instruction_is_frsp*/
4120	                                0, /*instruction_is_convert_to_64bit*/
4121	                                0, /*instruction_is_convert_to_32bit*/
4122	                                0); /*single-precision*/
4123	  product = tmp.d;
4124	}
4125	else {
4126	  /*HACK!*/
4127	  product = *(double*)frA * *(double*)frC;
4128	}
4129	/* compute the subtract */
4130	if (is_invalid_operation(processor, cia,
4131	                         product, *frB,
4132	                         fpscr_vxsnan | fpscr_vxisi,
4133	                         1, /*single?*/
4134	                         0) /*negate?*/) {
4135	  invalid_arithemetic_operation(processor, cia,
4136	                                frT, product, *frB, 0,
4137	                                0, /*instruction_is_frsp*/
4138	                                0, /*instruction_is_convert_to_64bit*/
4139	                                0, /*instruction_is_convert_to_32bit*/
4140	                                0); /*single-precision*/
4141	}
4142	else {
4143	  /*HACK!*/
4144	  float s = product - *(double*)frB;
4145	  *(double*)frT = (double)s;
4146	}
4147	FPSCR_END(Rc);
4148	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4149
41500.63,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add
4151*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   5,  5,  0
4152*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
4153*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
4154*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4155	FPSCR_BEGIN;
4156	double product; /*HACK! - incorrectly loosing precision ... */
4157	/* compute the multiply */
4158	if (is_invalid_operation(processor, cia,
4159	                         *frA, *frC,
4160	                         fpscr_vxsnan | fpscr_vximz,
4161	                         0, /*single?*/
4162	                         0) /*negate?*/) {
4163	  union { double d; unsigned64 u; } tmp;
4164	  invalid_arithemetic_operation(processor, cia,
4165	                                &tmp.u, *frA, 0, *frC,
4166	                                0, /*instruction_is_frsp*/
4167	                                0, /*instruction_is_convert_to_64bit*/
4168	                                0, /*instruction_is_convert_to_32bit*/
4169	                                0); /*single-precision*/
4170	  product = tmp.d;
4171	}
4172	else {
4173	  /*HACK!*/
4174	  product = *(double*)frA * *(double*)frC;
4175	}
4176	/* compute the add */
4177	if (is_invalid_operation(processor, cia,
4178	                         product, *frB,
4179	                         fpscr_vxsnan | fpscr_vxisi,
4180	                         0, /*single?*/
4181	                         0) /*negate?*/) {
4182	  invalid_arithemetic_operation(processor, cia,
4183	                                frT, product, *frB, 0,
4184	                                0, /*instruction_is_frsp*/
4185	                                0, /*instruction_is_convert_to_64bit*/
4186	                                0, /*instruction_is_convert_to_32bit*/
4187	                                0); /*single-precision*/
4188	}
4189	else {
4190	  /*HACK!*/
4191	  double s = -(product + *(double*)frB);
4192	  *(double*)frT = s;
4193	}
4194	FPSCR_END(Rc);
4195	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4196
41970.59,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add Single
4198*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
4199*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4200*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4201*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4202	FPSCR_BEGIN;
4203	float product; /*HACK! - incorrectly loosing precision ... */
4204	/* compute the multiply */
4205	if (is_invalid_operation(processor, cia,
4206	                         *frA, *frC,
4207	                         fpscr_vxsnan | fpscr_vximz,
4208	                         1, /*single?*/
4209	                         0) /*negate?*/) {
4210	  union { double d; unsigned64 u; } tmp;
4211	  invalid_arithemetic_operation(processor, cia,
4212	                                &tmp.u, *frA, 0, *frC,
4213	                                0, /*instruction_is_frsp*/
4214	                                0, /*instruction_is_convert_to_64bit*/
4215	                                0, /*instruction_is_convert_to_32bit*/
4216	                                0); /*single-precision*/
4217	  product = tmp.d;
4218	}
4219	else {
4220	  /*HACK!*/
4221	  product = *(double*)frA * *(double*)frC;
4222	}
4223	/* compute the add */
4224	if (is_invalid_operation(processor, cia,
4225	                         product, *frB,
4226	                         fpscr_vxsnan | fpscr_vxisi,
4227	                         1, /*single?*/
4228	                         0) /*negate?*/) {
4229	  invalid_arithemetic_operation(processor, cia,
4230	                                frT, product, *frB, 0,
4231	                                0, /*instruction_is_frsp*/
4232	                                0, /*instruction_is_convert_to_64bit*/
4233	                                0, /*instruction_is_convert_to_32bit*/
4234	                                0); /*single-precision*/
4235	}
4236	else {
4237	  /*HACK!*/
4238	  float s = -(product + *(double*)frB);
4239	  *(double*)frT = (double)s;
4240	}
4241	FPSCR_END(Rc);
4242	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4243
42440.63,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract
4245*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   5,  5,  0
4246*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
4247*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
4248*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4249	FPSCR_BEGIN;
4250	double product; /*HACK! - incorrectly loosing precision ... */
4251	/* compute the multiply */
4252	if (is_invalid_operation(processor, cia,
4253	                         *frA, *frC,
4254	                         fpscr_vxsnan | fpscr_vximz,
4255	                         0, /*single?*/
4256	                         0) /*negate?*/) {
4257	  union { double d; unsigned64 u; } tmp;
4258	  invalid_arithemetic_operation(processor, cia,
4259	                                &tmp.u, *frA, 0, *frC,
4260	                                0, /*instruction_is_frsp*/
4261	                                0, /*instruction_is_convert_to_64bit*/
4262	                                0, /*instruction_is_convert_to_32bit*/
4263	                                0); /*single-precision*/
4264	  product = tmp.d;
4265	}
4266	else {
4267	  /*HACK!*/
4268	  product = *(double*)frA * *(double*)frC;
4269	}
4270	/* compute the subtract */
4271	if (is_invalid_operation(processor, cia,
4272	                         product, *frB,
4273	                         fpscr_vxsnan | fpscr_vxisi,
4274	                         0, /*single?*/
4275	                         0) /*negate?*/) {
4276	  invalid_arithemetic_operation(processor, cia,
4277	                                frT, product, *frB, 0,
4278	                                0, /*instruction_is_frsp*/
4279	                                0, /*instruction_is_convert_to_64bit*/
4280	                                0, /*instruction_is_convert_to_32bit*/
4281	                                0); /*single-precision*/
4282	}
4283	else {
4284	  /*HACK!*/
4285	  double s = -(product - *(double*)frB);
4286	  *(double*)frT = s;
4287	}
4288	FPSCR_END(Rc);
4289	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4290
42910.59,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract Single
4292*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
4293*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4294*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4295*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4296	FPSCR_BEGIN;
4297	float product; /*HACK! - incorrectly loosing precision ... */
4298	/* compute the multiply */
4299	if (is_invalid_operation(processor, cia,
4300	                         *frA, *frC,
4301	                         fpscr_vxsnan | fpscr_vximz,
4302	                         1, /*single?*/
4303	                         0) /*negate?*/) {
4304	  union { double d; unsigned64 u; } tmp;
4305	  invalid_arithemetic_operation(processor, cia,
4306	                                &tmp.u, *frA, 0, *frC,
4307	                                0, /*instruction_is_frsp*/
4308	                                0, /*instruction_is_convert_to_64bit*/
4309	                                0, /*instruction_is_convert_to_32bit*/
4310	                                0); /*single-precision*/
4311	  product = tmp.d;
4312	}
4313	else {
4314	  /*HACK!*/
4315	  product = *(double*)frA * *(double*)frC;
4316	}
4317	/* compute the subtract */
4318	if (is_invalid_operation(processor, cia,
4319	                         product, *frB,
4320	                         fpscr_vxsnan | fpscr_vxisi,
4321	                         1, /*single?*/
4322	                         0) /*negate?*/) {
4323	  invalid_arithemetic_operation(processor, cia,
4324	                                frT, product, *frB, 0,
4325	                                0, /*instruction_is_frsp*/
4326	                                0, /*instruction_is_convert_to_64bit*/
4327	                                0, /*instruction_is_convert_to_32bit*/
4328	                                0); /*single-precision*/
4329	}
4330	else {
4331	  /*HACK!*/
4332	  float s = -(product - *(double*)frB);
4333	  *(double*)frT = (double)s;
4334	}
4335	FPSCR_END(Rc);
4336	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4337
4338
4339#
4340# I.4.6.6 Floating-Point Rounding and Conversion Instructions
4341#
4342
43430.63,6.FRT,11./,16.FRB,21.12,31.Rc:X:f::Floating Round to Single-Precision
4344*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
4345*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4346*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4347*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4348	int sign;
4349	int exp;
4350	unsigned64 frac_grx;
4351	/***/
4352	  /* split off cases for what to do */
4353	  if (EXTRACTED64(*frB, 1, 11) < 897
4354	      && EXTRACTED64(*frB, 1, 63) > 0) {
4355	      if ((FPSCR & fpscr_ue) == 0) GOTO(Disabled_Exponent_Underflow);
4356	      if ((FPSCR & fpscr_ue) != 0) GOTO(Enabled_Exponent_Underflow);
4357	  }
4358	  if (EXTRACTED64(*frB, 1, 11) > 1150
4359	      && EXTRACTED64(*frB, 1, 11) < 2047) {
4360	      if ((FPSCR & fpscr_oe) == 0) GOTO(Disabled_Exponent_Overflow);
4361	      if ((FPSCR & fpscr_oe) != 0) GOTO(Enabled_Exponent_Overflow);
4362	  }
4363	  if (EXTRACTED64(*frB, 1, 11) > 896
4364	      && EXTRACTED64(*frB, 1, 11) < 1151) GOTO(Normal_Operand);
4365	  if (EXTRACTED64(*frB, 1, 63) == 0) GOTO(Zero_Operand);
4366	  if (EXTRACTED64(*frB, 1, 11) == 2047) {
4367	    if (EXTRACTED64(*frB, 12, 63) == 0) GOTO(Infinity_Operand);
4368	    if (EXTRACTED64(*frB, 12, 12) == 1) GOTO(QNaN_Operand);
4369	    if (EXTRACTED64(*frB, 12, 12) == 0
4370	        && EXTRACTED64(*frB, 13, 63) > 0) GOTO(SNaN_Operand);
4371	  }
4372	/**/
4373	LABEL(Disabled_Exponent_Underflow):
4374	  sign = EXTRACTED64(*frB, 0, 0);
4375	  if (EXTRACTED64(*frB, 1, 11) == 0) {
4376	    exp = -1022;
4377	    frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4378	  }
4379	  if (EXTRACTED64(*frB, 1, 11) > 0) {
4380	    exp = EXTRACTED64(*frB, 1, 11) - 1023;
4381	    frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4382	  }
4383	    /* G|R|X == zero from above */
4384	    while (exp < -126) {
4385	      exp = exp + 1;
4386	      frac_grx = (INSERTED64(EXTRACTED64(frac_grx, 0, 54), 1, 55)
4387	                  | MASKED64(frac_grx, 55, 55));
4388	    }
4389	  FPSCR_SET_UX(EXTRACTED64(frac_grx, 24, 55) > 0);
4390	  Round_Single(processor, sign, &exp, &frac_grx);
4391	  FPSCR_SET_XX(FPSCR & fpscr_fi);
4392	  if (EXTRACTED64(frac_grx, 0, 52) == 0) {
4393	    *frT = INSERTED64(sign, 0, 0);
4394	    if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
4395	    if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
4396	  }
4397	  if (EXTRACTED64(frac_grx, 0, 52) > 0) {
4398	    if (EXTRACTED64(frac_grx, 0, 0) == 1) {
4399	      if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4400	      if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4401	    }
4402	    if (EXTRACTED64(frac_grx, 0, 0) == 0) {
4403	      if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_denormalized_number);
4404	      if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_denormalized_number);
4405	    }
4406	    /*Normalize_Operand:*/
4407	      while (EXTRACTED64(frac_grx, 0, 0) == 0) {
4408	        exp = exp - 1;
4409	        frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1,  52), 0, 51);
4410	      }
4411	    *frT = (INSERTED64(sign, 0, 0)
4412	            | INSERTED64(exp + 1023, 1, 11)
4413	            | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4414	  }
4415	  GOTO(Done);
4416	/**/
4417	LABEL(Enabled_Exponent_Underflow):
4418	  FPSCR_SET_UX(1);
4419	  sign = EXTRACTED64(*frB, 0, 0);
4420	  if (EXTRACTED64(*frB, 1, 11) == 0) {
4421	    exp = -1022;
4422	    frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4423	  }
4424	  if (EXTRACTED64(*frB, 1, 11) > 0) {
4425	    exp = EXTRACTED64(*frB, 1, 11) - 1023;
4426	    frac_grx = (BIT64(0) |
4427	                INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52));
4428	  }
4429	  /*Normalize_Operand:*/
4430	    while (EXTRACTED64(frac_grx, 0, 0) == 0) {
4431	      exp = exp - 1;
4432	      frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1, 52), 0, 51);
4433	    }
4434	  Round_Single(processor, sign, &exp, &frac_grx);
4435	  FPSCR_SET_XX(FPSCR & fpscr_fi);
4436	  exp = exp + 192;
4437	  *frT = (INSERTED64(sign, 0, 0)
4438	          | INSERTED64(exp + 1023, 1, 11)
4439	          | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4440	  if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4441	  if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4442	  GOTO(Done);
4443	/**/
4444	LABEL(Disabled_Exponent_Overflow):
4445	  FPSCR_SET_OX(1);
4446	  if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
4447	    if (EXTRACTED64(*frB, 0, 0) == 0) {
4448	      *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
4449	      FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
4450	    }
4451	    if (EXTRACTED64(*frB, 0, 0) == 1) {
4452	      *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
4453	      FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
4454	    }
4455	  }
4456	  if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_zero) {
4457	    if (EXTRACTED64(*frB, 0, 0) == 0) {
4458	      *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
4459	      FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4460	    }
4461	    if (EXTRACTED64(*frB, 0, 0) == 1) {
4462	      *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
4463	      FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4464	    }
4465	  }
4466	  if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_pos_infinity) {
4467	    if (EXTRACTED64(*frB, 0, 0) == 0) {
4468	      *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
4469	      FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
4470	    }
4471	    if (EXTRACTED64(*frB, 0, 0) == 1) {
4472	      *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
4473	      FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4474	    }
4475	  }
4476	  if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_neg_infinity) {
4477	    if (EXTRACTED64(*frB, 0, 0) == 0) {
4478	      *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
4479	      FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4480	    }
4481	    if (EXTRACTED64(*frB, 0, 0) == 1) {
4482	      *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
4483	      FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
4484	    }
4485	  }
4486	  /* FPSCR[FR] <- undefined */
4487	  FPSCR_SET_FI(1);
4488	  FPSCR_SET_XX(1);
4489	  GOTO(Done);
4490	/**/
4491	LABEL(Enabled_Exponent_Overflow):
4492	  sign = EXTRACTED64(*frB, 0, 0);
4493	  exp = EXTRACTED64(*frB, 1, 11) - 1023;
4494	  frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4495	  Round_Single(processor, sign, &exp, &frac_grx);
4496	  FPSCR_SET_XX(FPSCR & fpscr_fi);
4497	/**/
4498	LABEL(Enabled_Overflow):
4499	  FPSCR_SET_OX(1);
4500	  exp = exp - 192;
4501	  *frT = (INSERTED64(sign, 0, 0)
4502	          | INSERTED64(exp + 1023, 1, 11)
4503	          | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4504	  if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4505	  if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4506	  GOTO(Done);
4507	/**/
4508	LABEL(Zero_Operand):
4509	  *frT = *frB;
4510	  if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
4511	  if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
4512	  FPSCR_SET_FR(0);
4513	  FPSCR_SET_FI(0);
4514	  GOTO(Done);
4515	/**/
4516	LABEL(Infinity_Operand):
4517	  *frT = *frB;
4518	  if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
4519	  if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
4520	  FPSCR_SET_FR(0);
4521	  FPSCR_SET_FI(0);
4522	  GOTO(Done);
4523	/**/
4524	LABEL(QNaN_Operand):
4525	  *frT = INSERTED64(EXTRACTED64(*frB, 0, 34), 0, 34);
4526	  FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
4527	  FPSCR_SET_FR(0);
4528	  FPSCR_SET_FI(0);
4529	  GOTO(Done);
4530	/**/
4531	LABEL(SNaN_Operand):
4532	  FPSCR_OR_VX(fpscr_vxsnan);
4533	  if ((FPSCR & fpscr_ve) == 0) {
4534	    *frT = (MASKED64(*frB, 0, 11)
4535	            | BIT64(12)
4536	            | MASKED64(*frB, 13, 34));
4537	    FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
4538	  }
4539	  FPSCR_SET_FR(0);
4540	  FPSCR_SET_FI(0);
4541	  GOTO(Done);
4542	/**/
4543	LABEL(Normal_Operand):
4544	  sign = EXTRACTED64(*frB, 0, 0);
4545	  exp = EXTRACTED64(*frB, 1, 11) - 1023;
4546	  frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4547	  Round_Single(processor, sign, &exp, &frac_grx);
4548	  FPSCR_SET_XX(FPSCR & fpscr_fi);
4549	  if (exp > 127 && (FPSCR & fpscr_oe) == 0) GOTO(Disabled_Exponent_Overflow);
4550	  if (exp > 127 && (FPSCR & fpscr_oe) != 0) GOTO(Enabled_Overflow);
4551	  *frT = (INSERTED64(sign, 0, 0)
4552	          | INSERTED64(exp + 1023, 1, 11)
4553	          | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4554	  if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4555	  if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4556	  GOTO(Done);
4557	/**/
4558	LABEL(Done):
4559	  PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
4560
4561
45620.63,6.FRT,11./,16.FRB,21.814,31.Rc:X:64,f::Floating Convert To Integer Doubleword
4563	floating_point_assist_interrupt(processor, cia);
4564
45650.63,6.FRT,11./,16.FRB,21.815,31.Rc:X:64,f::Floating Convert To Integer Doubleword with round towards Zero
4566	floating_point_assist_interrupt(processor, cia);
4567
45680.63,6.FRT,11./,16.FRB,21.14,31.Rc:X:f::Floating Convert To Integer Word
4569	floating_point_assist_interrupt(processor, cia);
4570
45710.63,6.FRT,11./,16.FRB,21.15,31.Rc:X:f:fctiwz:Floating Convert To Integer Word with round towards Zero
4572*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
4573*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4574*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4575*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4576	FPSCR_BEGIN;
4577	convert_to_integer(processor, cia,
4578	                   frT, *frB,
4579	                   fpscr_rn_round_towards_zero, 32);
4580	FPSCR_END(Rc);
4581	PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
4582
45830.63,6.FRT,11./,16.FRB,21.846,31.Rc:X:64,f::Floating Convert from Integer Doubleword
4584	int sign = EXTRACTED64(*frB, 0, 0);
4585	int exp = 63;
4586	unsigned64 frac = *frB;
4587	/***/
4588	  if (frac == 0) GOTO(Zero_Operand);
4589	  if (sign == 1) frac = ~frac + 1;
4590	  while (EXTRACTED64(frac, 0, 0) == 0) {
4591	    /*??? do the loop 0 times if (FRB) = max negative integer */
4592	    frac = INSERTED64(EXTRACTED64(frac, 1, 63), 0, 62);
4593	    exp = exp - 1;
4594	  }
4595	  Round_Float(processor, sign, &exp, &frac, FPSCR & fpscr_rn);
4596	  if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4597	  if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4598	  *frT = (INSERTED64(sign, 0, 0)
4599	          | INSERTED64(exp + 1023, 1, 11)
4600	          | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
4601	  GOTO(Done);
4602	/**/
4603	LABEL(Zero_Operand):
4604	  FPSCR_SET_FR(0);
4605	  FPSCR_SET_FI(0);
4606	  FPSCR_SET_FPRF(fpscr_rf_pos_zero);
4607	  *frT = 0;
4608	  GOTO(Done);
4609	/**/
4610	LABEL(Done):
4611	  PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
4612
4613
4614#
4615# I.4.6.7 Floating-Point Compare Instructions
4616#
4617
46180.63,6.BF,9./,11.FRA,16.FRB,21.0,31./:X:f:fcmpu:Floating Compare Unordered
4619*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
4620*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4621*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4622*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4623	FPSCR_BEGIN;
4624	unsigned c;
4625	if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
4626	  c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
4627	else if (is_less_than(frA, frB))
4628	  c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
4629	else if (is_greater_than(frA, frB))
4630	  c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
4631	else
4632	  c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
4633	FPSCR_SET_FPCC(c);
4634	CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
4635	if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0))
4636	  FPSCR_OR_VX(fpscr_vxsnan);
4637	FPSCR_END(0);
4638	PPC_INSN_FLOAT_CR(0, FRA_BITMASK | FRB_BITMASK, BF_BITMASK);
4639
46400.63,6.BF,9./,11.FRA,16.FRB,21.32,31./:X:f:fcmpo:Floating Compare Ordered
4641*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
4642*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4643*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4644*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4645	FPSCR_BEGIN;
4646	unsigned c;
4647	if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
4648	  c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
4649	else if (is_less_than(frA, frB))
4650	  c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
4651	else if (is_greater_than(frA, frB))
4652	  c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
4653	else
4654	  c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
4655	FPSCR_SET_FPCC(c);
4656	CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
4657	if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0)) {
4658	  FPSCR_OR_VX(fpscr_vxsnan);
4659	  if ((FPSCR & fpscr_ve) == 0)
4660	    FPSCR_OR_VX(fpscr_vxvc);
4661	}
4662	else if (is_QNaN(*frA, 0) || is_QNaN(*frB, 0)) {
4663	  FPSCR_OR_VX(fpscr_vxvc);
4664	}
4665	FPSCR_END(0);
4666	PPC_INSN_FLOAT_CR(0, FRA_BITMASK | FRB_BITMASK, BF_BITMASK);
4667
4668
4669#
4670# I.4.6.8 Floating-Point Status and Control Register Instructions
4671#
4672
46730.63,6.FRT,11./,16./,21.583,31.Rc:X:f::Move From FPSCR
4674	FPSCR_BEGIN;
4675	*frT = FPSCR;
4676	FPSCR_END(Rc);
4677
46780.63,6.BF,9./,11.BFA,14./,16./,21.64,31./:X:f::Move to Condition Register from FPSCR
4679	FPSCR_BEGIN;
4680	unsigned field = FPSCR_FIELD(BFA);
4681	CR_SET(BF, field);
4682	FPSCR_SET(BFA, 0); /* FPSCR_END fixes up FEX/VX */
4683	FPSCR_END(0);
4684
46850.63,6.BF,9./,11./,16.U,20./,21.134,31.Rc:X:f::Move To FPSCR Field Immediate
4686	FPSCR_BEGIN;
4687	FPSCR_SET(BF, U);
4688	FPSCR_END(Rc);
4689
46900.63,6./,7.FLM,15./,16.FRB,21.711,31.Rc:XFL:f::Move To FPSCR Fields
4691	FPSCR_BEGIN;
4692	int i;
4693	for (i = 0; i < 8; i++) {
4694	  if ((FLM & BIT8(i))) {
4695	    FPSCR &= ~MASK32(i*4, i*4+3);
4696	    FPSCR |= MASKED32(*frB, i*4, i*4+3);
4697	  }
4698	}
4699	FPSCR_END(Rc);
4700
47010.63,6.BT,11./,16./,21.70,31.Rc:X:f::Move To FPSCR Bit 0
4702	FPSCR_BEGIN;
4703	unsigned32 bit = BIT32(BT);
4704	FPSCR &= ~bit;
4705	FPSCR_END(Rc);
4706
47070.63,6.BT,11./,16./,21.38,31.Rc:X:f::Move To FPSCR Bit 1
4708	FPSCR_BEGIN;
4709	unsigned32 bit = BIT32(BT);
4710	if (bit & fpscr_fi)
4711	  bit |= fpscr_xx;
4712	if ((bit & fpscr_vx_bits))
4713	  bit |= fpscr_fx;
4714	/* note - omit vx bit */
4715	if ((bit & (fpscr_ox | fpscr_ux | fpscr_zx | fpscr_xx)))
4716	  bit |= fpscr_fx;
4717	FPSCR |= bit;
4718	FPSCR_END(Rc);
4719
4720#
4721# I.A.1.2 Floating-Point Arithmetic Instructions
4722#
4723
47240.63,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f,o::Floating Square Root
4725	program_interrupt(processor, cia, optional_instruction_program_interrupt);
4726
47270.59,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f,o::Floating Square Root Single
4728	program_interrupt(processor, cia, optional_instruction_program_interrupt);
4729
47300.59,6.FRT,11./,16.FRB,21./,26.24,31.Rc:A:f,o::Floating Reciprocal Estimate Single
4731	program_interrupt(processor, cia, optional_instruction_program_interrupt);
4732
47330.63,6.FRT,11./,16.FRB,21./,26.26,31.Rc:A:f,o::Floating Reciprocal Square Root Estimate
4734	program_interrupt(processor, cia, optional_instruction_program_interrupt);
4735
4736#
4737# I.A.1.3 Floating-Point Select Instruction
4738#
4739
47400.63,6.FRT,11.FRA,16.FRB,21.FRC,26.23,31.Rc:A:f,o::Floating Select
4741*601: PPC_UNIT_BAD,   PPC_UNIT_BAD,   0,  0,  0
4742*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4743*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4744*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4745	if (CURRENT_MODEL == MODEL_ppc601) {
4746	  program_interrupt(processor, cia, optional_instruction_program_interrupt);
4747	} else {
4748	  unsigned64 zero = 0;
4749	  FPSCR_BEGIN;
4750	  if (is_NaN(*frA, 0) || is_less_than (frA, &zero)) *frT = *frB;
4751	  else						    *frT = *frC;
4752	  FPSCR_END(Rc);
4753	  PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4754	}
4755
4756#
4757# II.3.2 Cache Management Instructions
4758#
4759
47600.31,6./,11.RA,16.RB,21.982,31./:X::icbi:Instruction Cache Block Invalidate
4761*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4762*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
4763*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
4764*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  1,  0
4765	/* blindly flush all instruction cache entries */
4766	#if WITH_IDECODE_CACHE_SIZE
4767	cpu_flush_icache(processor);
4768	#endif
4769	PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0);
4770
47710.19,6./,11./,16./,21.150,31./:XL::isync:Instruction Synchronize
4772*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4773*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
4774*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
4775*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  1,  0
4776	cpu_synchronize_context(processor, cia);
4777	PPC_INSN_INT(0, 0, 0);
4778
4779
4780#
4781# II.3.2.2 Data Cache Instructions
4782#
4783
47840.31,6./,11.RA,16.RB,21.278,31./:X:::Data Cache Block Touch
4785*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4786*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   2,  2,  0
4787*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   2,  2,  0
4788*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  1,  0
4789	TRACE(trace_tbd,("Data Cache Block Touch\n"));
4790	PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4791
47920.31,6./,11.RA,16.RB,21.246,31./:X:::Data Cache Block Touch for Store
4793*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4794*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   2,  2,  0
4795*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   2,  2,  0
4796*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
4797	TRACE(trace_tbd,("Data Cache Block Touch for Store\n"));
4798	PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4799
48000.31,6./,11.RA,16.RB,21.1014,31./:X:::Data Cache Block set to Zero
4801*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4802*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   10, 10, 0
4803*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   10, 10, 0
4804*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
4805	TRACE(trace_tbd,("Data Cache Block set to Zero\n"));
4806	PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4807
48080.31,6./,11.RA,16.RB,21.54,31./:X:::Data Cache Block Store
4809*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4810*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   5,  5,  0
4811*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   5,  5,  0
4812*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  1,  0
4813	TRACE(trace_tbd,("Data Cache Block Store\n"));
4814	PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4815
48160.31,6./,11.RA,16.RB,21.86,31./:X:::Data Cache Block Flush
4817*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4818*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   5,  5,  0
4819*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   5,  5,  0
4820*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  1,  0
4821	TRACE(trace_tbd,("Data Cache Block Flush\n"));
4822	PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4823
4824#
4825# II.3.3 Enforce In-order Execution of I/O Instruction
4826#
4827
48280.31,6./,11./,16./,21.854,31./:X::eieio:Enforce In-order Execution of I/O
4829	/* Since this model has no instruction overlap
4830	   this instruction need do nothing */
4831
4832#
4833# II.4.1 Time Base Instructions
4834#
4835
48360.31,6.RT,11.tbr,21.371,31./:XFX::mftb:Move From Time Base
4837*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
4838*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
4839*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  3,  3,  0
4840	int n = (tbr{5:9} << 5) | tbr{0:4};
4841	if (n == 268) {
4842	  if (is_64bit_implementation) *rT = TB;
4843	  else                         *rT = EXTRACTED64(TB, 32, 63);
4844	}
4845	else if (n == 269) {
4846	  if (is_64bit_implementation) *rT = EXTRACTED64(TB, 0, 31);
4847	  else                         *rT = EXTRACTED64(TB, 0, 31);
4848	}
4849	else
4850	  program_interrupt(processor, cia,
4851	                    illegal_instruction_program_interrupt);
4852
4853
4854#
4855# III.2.3.1 System Linkage Instructions
4856#
4857
48580.19,6./,11./,16./,21.50,31./:XL::rfi:Return From Interrupt
4859*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4860*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   3,  3,  0
4861*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   3,  3,  0
4862*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  3,  3,  0
4863	if (IS_PROBLEM_STATE(processor)) {
4864	  program_interrupt(processor, cia,
4865	                    privileged_instruction_program_interrupt);
4866	}
4867	else {
4868	  MSR = (MASKED(SRR1, 0, 32)
4869	         | MASKED(SRR1, 37, 41)
4870	         | MASKED(SRR1, 48, 63));
4871	  NIA = MASKED(SRR0, 0, 61);
4872	  cpu_synchronize_context(processor, cia);
4873	  check_masked_interrupts(processor);
4874	}
4875
4876#
4877# III.3.4.1 Move to/from System Register Instructions
4878#
4879
4880#0.31,6.RS,11.SPR,21.467,31./:XFX:::Move To Special Purpose Register
4881#0.31,6.RT,11.SPR,21.339,31./:XFX:::Move From Special Purpose Register
48820.31,6.RS,11./,16./,21.146,31./:X:::Move To Machine State Register
4883*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4884*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   2,  2,  0
4885*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   2,  2,  0
4886*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  1,  1,  0
4887	if (IS_PROBLEM_STATE(processor))
4888	  program_interrupt(processor, cia,
4889	                    privileged_instruction_program_interrupt);
4890	else {
4891	  MSR = *rS;
4892	  check_masked_interrupts(processor);
4893	}
4894
48950.31,6.RT,11./,16./,21.83,31./:X:::Move From Machine State Register
4896*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4897*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
4898*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
4899*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  3,  3,  0
4900	if (IS_PROBLEM_STATE(processor))
4901	  program_interrupt(processor, cia,
4902	                    privileged_instruction_program_interrupt);
4903	else {
4904	  *rT = MSR;
4905	  check_masked_interrupts(processor);
4906	}
4907
4908
4909#
4910# III.4.11.1 Cache Management Instructions
4911#
4912
49130.31,6./,11.RA,16.RB,21.470,31./:X::dcbi:Data Cache Block Invalidate
4914*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4915*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   2,  2,  0
4916*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   2,  2,  0
4917*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
4918	if (IS_PROBLEM_STATE(processor))
4919	  program_interrupt(processor, cia,
4920	                    privileged_instruction_program_interrupt);
4921	else
4922	  TRACE(trace_tbd,("Data Cache Block Invalidate\n"));
4923
4924#
4925# III.4.11.2 Segment Register Manipulation Instructions
4926#
4927
49280.31,6.RS,11./,12.SR,16./,21.210,31./:X:32:mtsr %SR,%RS:Move To Segment Register
4929*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4930*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   2,  2,  0
4931*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   2,  2,  0
4932*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  1,  1,  0
4933	if (IS_PROBLEM_STATE(processor))
4934	  program_interrupt(processor, cia,
4935	                    privileged_instruction_program_interrupt);
4936	else
4937	  SEGREG(SR) = *rS;
4938
49390.31,6.RS,11./,16.RB,21.242,31./:X:32:mtsrin %RS,%RB:Move To Segment Register Indirect
4940*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4941*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   2,  2,  0
4942*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   2,  2,  0
4943*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  1,  1,  0
4944	if (IS_PROBLEM_STATE(processor))
4945	  program_interrupt(processor, cia,
4946	                    privileged_instruction_program_interrupt);
4947	else
4948	  SEGREG(EXTRACTED32(*rB, 0, 3)) = *rS;
4949
49500.31,6.RT,11./,12.SR,16./,21.595,31./:X:32:mfsr %RT,%RS:Move From Segment Register
4951*601: PPC_UNIT_IU,    PPC_UNIT_IU,    2,  2,  0
4952*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   3,  3,  0
4953*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   3,  3,  0
4954*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  1,  1,  0
4955	if (IS_PROBLEM_STATE(processor))
4956	  program_interrupt(processor, cia,
4957	                    privileged_instruction_program_interrupt);
4958	else
4959	  *rT = SEGREG(SR);
4960
49610.31,6.RT,11./,16.RB,21.659,31./:X:32:mfsrin %RT,%RB:Move From Segment Register Indirect
4962*601: PPC_UNIT_IU,    PPC_UNIT_IU,    2,  2,  0
4963*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   3,  3,  0
4964*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   3,  3,  0
4965*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  1,  1,  0
4966	if (IS_PROBLEM_STATE(processor))
4967	  program_interrupt(processor, cia,
4968	                    privileged_instruction_program_interrupt);
4969	else
4970	  *rT = SEGREG(EXTRACTED32(*rB, 0, 3));
4971
4972
4973#
4974# III.4.11.3 Lookaside Buffer Management Instructions (Optional)
4975#
4976
49770.31,6./,11./,16.RB,21.434,31./:X:64::SLB Invalidate Entry
4978
49790.31,6./,11./,16./,21.498,31./:X:64::SLB Invalidate All
4980
49810.31,6./,11./,16.RB,21.306,31./:X:::TLB Invalidate Entry
4982	if (IS_PROBLEM_STATE(processor))
4983	  program_interrupt(processor, cia,
4984	                    privileged_instruction_program_interrupt);
4985	else {
4986	  int nr = 0;
4987	  cpu *proc;
4988	  while (1) {
4989	    proc = psim_cpu(cpu_system(processor), nr);
4990	    if (proc == NULL) break;
4991	    cpu_page_tlb_invalidate_entry(proc, *rB);
4992	    nr++;
4993	  }
4994	}
4995
49960.31,6./,11./,16./,21.370,31./:X:::TLB Invalidate All
4997	if (IS_PROBLEM_STATE(processor))
4998	  program_interrupt(processor, cia,
4999	                    privileged_instruction_program_interrupt);
5000	else {
5001	  int nr = 0;
5002	  cpu *proc;
5003	  while (1) {
5004	    proc = psim_cpu(cpu_system(processor), nr);
5005	    if (proc == NULL) break;
5006	    cpu_page_tlb_invalidate_all(proc);
5007	    nr++;
5008	  }
5009	}
5010
50110.31,6./,11./,16./,21.566,31./:X:::TLB Synchronize
5012	/* nothing happens here - always in sync */
5013
5014#
5015# III.A.1.2 External Access Instructions
5016#
5017
50180.31,6.RT,11.RA,16.RB,21.310,31./:X:earwax::External Control In Word Indexed
5019
50200.31,6.RS,11.RA,16.RB,21.438,31./:X:earwax::External Control Out Word Indexed
5021
5022:include:::altivec.igen
5023:include:::e500.igen
5024