xref: /netbsd-src/external/gpl3/gdb/dist/sim/ppc/powerpc.igen (revision 4b169a6ba595ae283ca507b26b15fdff40495b1c)
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:::uint32_t: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:::uint32_t:RT_BITMASK:RT:(1 << RT)
43:cache::::RS:RS:
44:cache:::signed_word *:rS:RS:(cpu_registers(processor)->gpr + RS)
45:cache:::uint32_t:RS_BITMASK:RS:(1 << RS)
46:cache::::RB:RB:
47:cache:::signed_word *:rB:RB:(cpu_registers(processor)->gpr + RB)
48:cache:::uint32_t:RB_BITMASK:RB:(1 << RB)
49:scratch::::FRA:FRA:
50:cache:::uint64_t *:frA:FRA:(cpu_registers(processor)->fpr + FRA)
51:cache:::uint32_t:FRA_BITMASK:FRA:(1 << FRA)
52:scratch::::FRB:FRB:
53:cache:::uint64_t *:frB:FRB:(cpu_registers(processor)->fpr + FRB)
54:cache:::uint32_t:FRB_BITMASK:FRB:(1 << FRB)
55:scratch::::FRC:FRC:
56:cache:::uint64_t *:frC:FRC:(cpu_registers(processor)->fpr + FRC)
57:cache:::uint32_t:FRC_BITMASK:FRC:(1 << FRC)
58:scratch::::FRS:FRS:
59:cache:::uint64_t *:frS:FRS:(cpu_registers(processor)->fpr + FRS)
60:cache:::uint32_t:FRS_BITMASK:FRS:(1 << FRS)
61:scratch::::FRT:FRT:
62:cache:::uint64_t *:frT:FRT:(cpu_registers(processor)->fpr + FRT)
63:cache:::uint32_t:FRT_BITMASK:FRT:(1 << FRT)
64:cache:::unsigned_word:EXTS_SI:SI:((signed_word)(int16_t)instruction)
65:scratch::::BI:BI:
66:cache::::BIT32_BI:BI:BIT32(BI)
67:cache::::BF:BF:
68:cache:::uint32_t:BF_BITMASK:BF:(1 << BF)
69:scratch::::BA:BA:
70:cache::::BIT32_BA:BA:BIT32(BA)
71:cache:::uint32_t:BA_BITMASK:BA:(1 << BA)
72:scratch::::BB:BB:
73:cache::::BIT32_BB:BB:BIT32(BB)
74:cache:::uint32_t:BB_BITMASK:BB:(1 << BB)
75:cache::::BT:BT:
76:cache:::uint32_t:BT_BITMASK:BT:(1 << BT)
77:cache:::unsigned_word:EXTS_BD_0b00:BD:(((signed_word)(int16_t)instruction) & ~3)
78:cache:::unsigned_word:EXTS_LI_0b00:LI:((((signed_word)(int32_t)(instruction << 6)) >> 6) & ~0x3)
79:cache:::unsigned_word:EXTS_D:D:((signed_word)(int16_t)(instruction))
80:cache:::unsigned_word:EXTS_DS_0b00:DS:(((signed_word)(int16_t)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	  int16_t	    issue;			/* # cycles before function unit can process other insns */
178	  int16_t	    done;			/* # cycles before insn is done */
179	  uint32_t	    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	  uint32_t int_busy;				/* int registers that are busy */
197	  uint32_t fp_busy;				/* floating point registers that are busy */
198	  uint32_t cr_fpscr_busy;			/* CR/FPSCR registers that are busy */
199	  int16_t spr_busy;				/* SPR register that is busy or PPC_NO_SPR */
200	  uint32_t vr_busy;				/* AltiVec registers that are busy */
201	  int16_t vscr_busy;				/* AltiVec status register busy */
202	  int16_t issue;				/* # of cycles until unit can accept another insn */
203	  int16_t done;				/* # of cycles until insn is done */
204	  int16_t 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	  uint32_t int_busy;				/* int registers that are busy */
229	  uint32_t fp_busy;				/* floating point registers that are busy */
230	  uint32_t cr_fpscr_busy;			/* CR/FPSCR registers that are busy */
231	  uint8_t spr_busy[nr_of_sprs];		/* SPR registers that are busy */
232	  uint32_t vr_busy;				/* AltiVec registers that are busy */
233	  uint8_t vscr_busy;				/* AltiVec SC register busy */
234	  uint8_t 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 %s 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, uint32_t int_mask, uint32_t fp_mask, uint32_t 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, uint32_t int_busy, uint32_t fp_busy, uint32_t 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	uint32_t 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 uint32_t out_mask, const uint32_t in_mask
537	const uint32_t 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 uint32_t out_mask, const uint32_t in_mask, const uint32_t cr_mask
563	const uint32_t 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 uint32_t out_mask, const uint32_t in_mask
595	const uint32_t 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 uint32_t out_mask, const uint32_t in_mask
622	const uint32_t 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 uint32_t out_mask, const uint32_t in_mask, const uint32_t cr_mask
647	const uint32_t 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 uint32_t out_int_mask, const uint32_t out_fp_mask, const uint32_t in_int_mask, const uint32_t in_fp_mask
674	const uint32_t int_mask = out_int_mask | in_int_mask;
675	const uint32_t 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 uint32_t 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 uint32_t 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 register
738void::model-function::ppc_insn_mfcr:itable_index index, model_data *model_ptr, uint32_t int_mask
739	const uint32_t 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, uint32_t int_mask, unsigned FXM
759	int f;
760	int nr_crs = 0;
761	uint32_t 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 < ARRAY_SIZE (ppc_branch_conditional_name); 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
999uint64_t::function::DOUBLE:uint32_t WORD
1000	uint64_t 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	  uint64_t 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
1041uint32_t::function::SINGLE:uint64_t FRS
1042	uint32_t 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	  uint64_t 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, uint64_t *frac_grx
1073	/* comparisons ignore u bits */
1074	uint64_t 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, uint64_t *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, uint64_t *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, uint64_t *frt, uint64_t frb, fpscreg round_mode, int tgt_precision
1167	int i;
1168	int exp = 0;
1169	uint64_t 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	      && (int64_t)frac > (int64_t)MASK64(33+1, 63)/*2^31-1 >>1*/)
1210	    GOTO(Large_Operand);
1211	  if (tgt_precision == 64 /* can ignore frac64 in compare */
1212	      && (int64_t)frac > (int64_t)MASK64(1+1, 63)/*2^63-1 >>1*/)
1213	    GOTO(Large_Operand);
1214	  if (tgt_precision == 32 /* can ignore frac64 in compare */
1215	      && (int64_t)frac < (int64_t)MASK64(0, 32+1)/*-2^31 >>1*/)
1216	    GOTO(Large_Operand);
1217	  if (tgt_precision == 64 /* can ignore frac64 in compare */
1218	      && (int64_t)frac < (int64_t)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:uint64_t FRS
1288	return (MASKED64(FRS, 0, 0)
1289	        ? -1
1290	        : 1);
1291int::function::biased_exp:uint64_t frs, int single
1292	if (single)
1293	  return EXTRACTED64(frs, 1, 8);
1294	else
1295	  return EXTRACTED64(frs, 1, 11);
1296uint64_t::function::fraction:uint64_t 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:uint64_t frs, int single
1305	int exp = biased_exp(frs, single);
1306	return (exp >= 1
1307	        && exp <= (single ? 254 : 2046));
1308int::function::is_zero:uint64_t FRS
1309	return (MASKED64(FRS, 1, 63) == 0
1310	        ? sign(FRS)
1311	        : 0);
1312int::function::is_den:uint64_t frs, int single
1313	int exp = biased_exp(frs, single);
1314	uint64_t frac = fraction(frs, single);
1315	return (exp == 0 && frac != 0
1316	        ? sign(frs)
1317	        : 0);
1318int::function::is_inf:uint64_t frs, int single
1319	int exp = biased_exp(frs, single);
1320	uint64_t frac = fraction(frs, single);
1321	return (exp == (single ? 255 : 2047) && frac == 0
1322	        ? sign(frs)
1323	        : 0);
1324int::function::is_NaN:uint64_t frs, int single
1325	int exp = biased_exp(frs, single);
1326	uint64_t frac = fraction(frs, single);
1327	return (exp == (single ? 255 : 2047) && frac != 0
1328	        ? sign(frs)
1329	        : 0);
1330int::function::is_SNaN:uint64_t 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:uint64_t frs, int single
1336	return (is_NaN(frs, single) && !is_SNaN(frs, single));
1337int::function::is_less_than:uint64_t *fra, uint64_t *frb
1338	return *(double*)fra < *(double*)frb;
1339int::function::is_greater_than:uint64_t *fra, uint64_t *frb
1340	return *(double*)fra > *(double*)frb;
1341int::function::is_equan_to:uint64_t *fra, uint64_t *frb
1342	return *(double*)fra == *(double*)frb;
1343
1344
1345# which quiet nan should become the result
1346uint64_t::function::select_qnan:uint64_t fra, uint64_t frb, uint64_t frc, int instruction_is_frsp, int generate_qnan, int single
1347	uint64_t 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, uint64_t fra, uint64_t 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, uint64_t *frt, uint64_t fra, uint64_t frb, uint64_t 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, uint64_t fra, uint64_t 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, uint64_t *frt, uint64_t fra, uint64_t 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 (MPC860C0_PAGE_SIZE - (CIA & (MPC860C0_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 (MPC860C0_PAGE_SIZE - (CIA & (MPC860C0_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 (MPC860C0_PAGE_SIZE - (CIA & (MPC860C0_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	int64_t a = (int32_t)(*rA);
2700	int64_t b = (int32_t)(*rB);
2701	int64_t 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	int64_t a = (int32_t)(*rA);
2717	int64_t b = (int32_t)(*rB);
2718	int64_t 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	uint64_t a = (uint32_t)(*rA);
2732	uint64_t b = (uint32_t)(*rB);
2733	uint64_t 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	int64_t dividend = (int32_t)(*rA);
2747	int64_t divisor = (int32_t)(*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	  int64_t 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	uint64_t dividend = (uint32_t)(*rA);
2769	uint64_t divisor = (uint32_t)(*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	  uint64_t 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)(int8_t)*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)(int16_t)*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)(int32_t)*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#	uint64_t mask = BIT64(0);
3117#	uint64_t 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	uint32_t mask = BIT32(0);
3132	uint32_t 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	uint32_t s = *rS;
3181	uint32_t r = ROTL32(s, n);
3182	uint32_t 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	uint32_t r = ROTL32(*rS, n);
3213	uint32_t 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	uint32_t r = ROTL32(*rS, n);
3234	uint32_t 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	uint32_t 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	uint32_t 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	uint64_t mask;
3316	int n = MASKED(*rB, 59, 63);
3317	int32_t source = (int32_t)*rS; /* signed to keep sign bit */
3318	int S = (MASKED(*rS,32,32) != 0);
3319	int64_t r = ((uint64_t) source);
3320	r = ((uint64_t) source) << 32 | (uint32_t) source;
3321	r = ROTL64(r,64-n);
3322	if (MASKED(*rB,58,58) == 0)
3323		mask = (uint64_t) MASK64(n+32,63);
3324	else
3325		mask = (uint64_t) 0;
3326	*rA = (signed_word) ((r & mask) | (((int64_t) -1*S) & ~mask)); /* if 64bit will sign extend */
3327	if (S && (MASKED(r & ~mask,32,63)!=0))
3328	  XER |= xer_carry;
3329	else
3330	  XER &= ~xer_carry;
3331	CR0_COMPARE(*rA, 0, Rc);
3332	ITRACE(trace_alu, (" Result = %ld (0x%lx), XER = %ld\n",
3333			   (long)*rA, (long)*rA, (long)XER));
3334	PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3335
3336#
3337# I.3.3.14 Move to/from System Register Instructions
3338#
3339
33400.31,6.RS,11.SPR,21.467,31./:XFX::mtspr %SPR, %RS:Move to Special Purpose Register
3341*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3342*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   2,  2,  0
3343*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   2,  2,  0
3344*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  1,  1,  0
3345	int n = (SPR{5:9} << 5) | SPR{0:4};
3346	if (SPR{0} && IS_PROBLEM_STATE(processor))
3347	  program_interrupt(processor, cia,
3348	                    privileged_instruction_program_interrupt);
3349	else if (!spr_is_valid(n)
3350	         || spr_is_readonly(n))
3351	  program_interrupt(processor, cia,
3352	                    illegal_instruction_program_interrupt);
3353	else {
3354	  spreg new_val = (spr_length(n) == 64
3355			   ? *rS
3356			   : MASKED(*rS, 32, 63));
3357	  /* HACK - time base registers need to be updated immediately */
3358	  if (WITH_TIME_BASE) {
3359	    switch (n) {
3360	    case spr_tbu:
3361	      cpu_set_time_base(processor,
3362	                        (MASKED64(cpu_get_time_base(processor), 32, 63)
3363	                         | INSERTED64(new_val, 0, 31)));
3364	      break;
3365	    case spr_tbl:
3366	      cpu_set_time_base(processor,
3367	                        (MASKED64(cpu_get_time_base(processor), 0, 31)
3368	                         | INSERTED64(new_val, 32, 63)));
3369	      break;
3370	    case spr_dec:
3371	      cpu_set_decrementer(processor, new_val);
3372	      break;
3373	    default:
3374	      SPREG(n) = new_val;
3375	      break;
3376	    }
3377	  }
3378	  else {
3379	    SPREG(n) = new_val;
3380	  }
3381	}
3382	PPC_INSN_TO_SPR(RS_BITMASK, n);
3383
33840.31,6.RT,11.SPR,21.339,31./:XFX::mfspr %RT, %SPR:Move from Special Purpose Register
3385*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3386*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
3387*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
3388*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  3,  3,  0
3389	int n = (SPR{5:9} << 5) | SPR{0:4};
3390	if (SPR{0} && IS_PROBLEM_STATE(processor))
3391	  program_interrupt(processor, cia,
3392	                    privileged_instruction_program_interrupt);
3393	else if (!spr_is_valid(n))
3394	  program_interrupt(processor, cia,
3395	                    illegal_instruction_program_interrupt);
3396	else {
3397	  /* HACK - time base registers need to be calculated */
3398	  if (WITH_TIME_BASE) {
3399	    switch (n) {
3400	    case spr_dec:
3401	      *rT = cpu_get_decrementer(processor);
3402	      break;
3403		case spr_tbrl:
3404	  	  if (is_64bit_implementation) *rT = TB;
3405	  	  else                         *rT = EXTRACTED64(TB, 32, 63);
3406		break;
3407		case spr_tbru:
3408	  	  if (is_64bit_implementation) *rT = EXTRACTED64(TB, 0, 31);
3409		  else                         *rT = EXTRACTED64(TB, 0, 31);
3410		break;
3411	    case spr_tbu:
3412	    case spr_tbl:
3413	      /* NOTE - these SPR's are not readable. Use mftb[ul] */
3414	    default:
3415	      *rT = SPREG(n);
3416	      break;
3417	    }
3418	  }
3419	  else {
3420	    *rT = SPREG(n);
3421	  }
3422	}
3423	PPC_INSN_FROM_SPR(RT_BITMASK, n);
3424
34250.31,6.RS,11./,12.FXM,20./,21.144,31./:XFX::mtfcr:Move to Condition Register Fields
3426*601: PPC_UNIT_IU,    PPC_UNIT_IU,    2,  2,  0
3427*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
3428*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
3429*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  1,  1,  0
3430	if (FXM == 0xff) {
3431	  CR = *rS;
3432	}
3433	else {
3434	  unsigned_word mask = 0;
3435	  unsigned_word f;
3436	  for (f = 0; f < 8; f++) {
3437	    if (FXM & (0x80 >> f))
3438	      mask |= (0xf << 4*(7-f));
3439	  }
3440	  CR = (MASKED(*rS, 32, 63) & mask) | (CR & ~mask);
3441	}
3442	PPC_INSN_MTCR(RS_BITMASK, FXM);
3443
34440.31,6.BF,9./,11./,16./,21.512,31./:X:::Move to Condition Register from XER
3445#	CR_SET(BF, EXTRACTED32(XER, 0, 3));
3446#	MBLIT32(XER, 0, 3, 0);
3447
34480.31,6.RT,11./,16./,21.19,31./:X:::Move From Condition Register
3449*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3450*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
3451*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
3452*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  3,  3,  0
3453	*rT = (uint32_t)CR;
3454	PPC_INSN_MFCR(RT_BITMASK);
3455
3456#
3457# I.4.6.2 Floating-Point Load Instructions
3458#
3459
34600.48,6.FRT,11.RA,16.D:D:f:lfs:Load Floating-Point Single
3461*601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
3462*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3463*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3464*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3465	unsigned_word b;
3466	unsigned_word EA;
3467	if (RA_is_0) b = 0;
3468	else         b = *rA;
3469	EA = b + EXTS(D);
3470	*frT = DOUBLE(MEM(unsigned, EA, 4));
3471	PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3472
34730.31,6.FRT,11.RA,16.RB,21.535,31./:X:f::Load Floating-Point Single Indexed
3474*601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
3475*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3476*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3477*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3478	unsigned_word b;
3479	unsigned_word EA;
3480	if (RA_is_0) b = 0;
3481	else         b = *rA;
3482	EA = b + *rB;
3483	*frT = DOUBLE(MEM(unsigned, EA, 4));
3484	PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3485
34860.49,6.FRT,11.RA,16.D:D:f::Load Floating-Point Single with Update
3487*601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
3488*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3489*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3490*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3491	unsigned_word EA;
3492	if (RA_is_0)
3493	  program_interrupt(processor, cia,
3494	                    illegal_instruction_program_interrupt);
3495	EA = *rA + EXTS(D);
3496	*frT = DOUBLE(MEM(unsigned, EA, 4));
3497	*rA = EA;
3498	PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3499
35000.31,6.FRT,11.RA,16.RB,21.567,31./:X:f::Load Floating-Point Single with Update Indexed
3501*601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
3502*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3503*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3504*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3505	unsigned_word EA;
3506	if (RA_is_0)
3507	  program_interrupt(processor, cia,
3508	                    illegal_instruction_program_interrupt);
3509	EA = *rA + *rB;
3510	*frT = DOUBLE(MEM(unsigned, EA, 4));
3511	*rA = EA;
3512	PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3513
35140.50,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double
3515*601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
3516*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3517*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3518*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3519	unsigned_word b;
3520	unsigned_word EA;
3521	if (RA_is_0) b = 0;
3522	else         b = *rA;
3523	EA = b + EXTS(D);
3524	*frT = MEM(unsigned, EA, 8);
3525	PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3526
35270.31,6.FRT,11.RA,16.RB,21.599,31./:X:f::Load Floating-Point Double Indexed
3528*601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
3529*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3530*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3531*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3532	unsigned_word b;
3533	unsigned_word EA;
3534	if (RA_is_0) b = 0;
3535	else         b = *rA;
3536	EA = b + *rB;
3537	*frT = MEM(unsigned, EA, 8);
3538	PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3539
35400.51,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double with Update
3541*601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
3542*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3543*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3544*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3545	unsigned_word EA;
3546	if (RA_is_0)
3547	  program_interrupt(processor, cia,
3548	                    illegal_instruction_program_interrupt);
3549	EA = *rA + EXTS(D);
3550	*frT = MEM(unsigned, EA, 8);
3551	*rA = EA;
3552	PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3553
35540.31,6.FRT,11.RA,16.RB,21.631,31./:X:f::Load Floating-Point Double with Update Indexed
3555*601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
3556*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3557*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3558*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3559	unsigned_word EA;
3560	if (RA_is_0)
3561	  program_interrupt(processor, cia,
3562	                    illegal_instruction_program_interrupt);
3563	EA = *rA + *rB;
3564	*frT = MEM(unsigned, EA, 8);
3565	*rA = EA;
3566	PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3567
3568
3569#
3570# I.4.6.3 Floating-Point Store Instructions
3571#
3572
35730.52,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single
3574*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3575*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3576*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3577*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3578	unsigned_word b;
3579	unsigned_word EA;
3580	if (RA_is_0) b = 0;
3581	else         b = *rA;
3582	EA = b + EXTS(D);
3583	STORE(EA, 4, SINGLE(*frS));
3584	PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3585
35860.31,6.FRS,11.RA,16.RB,21.663,31./:X:f::Store Floating-Point Single Indexed
3587*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3588*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3589*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3590*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3591	unsigned_word b;
3592	unsigned_word EA;
3593	if (RA_is_0) b = 0;
3594	else         b = *rA;
3595	EA = b + *rB;
3596	STORE(EA, 4, SINGLE(*frS));
3597	PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3598
35990.53,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single with Update
3600*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3601*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3602*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3603*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3604	unsigned_word EA;
3605	if (RA_is_0)
3606	  program_interrupt(processor, cia,
3607	                    illegal_instruction_program_interrupt);
3608	EA = *rA + EXTS(D);
3609	STORE(EA, 4, SINGLE(*frS));
3610	*rA = EA;
3611	PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3612
36130.31,6.FRS,11.RA,16.RB,21.695,31./:X:f::Store Floating-Point Single with Update Indexed
3614*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3615*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3616*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3617*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3618	unsigned_word EA;
3619	if (RA_is_0)
3620	  program_interrupt(processor, cia,
3621	                    illegal_instruction_program_interrupt);
3622	EA = *rA + *rB;
3623	STORE(EA, 4, SINGLE(*frS));
3624	*rA = EA;
3625	PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3626
36270.54,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double
3628*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3629*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3630*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3631*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3632	unsigned_word b;
3633	unsigned_word EA;
3634	if (RA_is_0) b = 0;
3635	else         b = *rA;
3636	EA = b + EXTS(D);
3637	STORE(EA, 8, *frS);
3638	PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3639
36400.31,6.FRS,11.RA,16.RB,21.727,31./:X:f::Store Floating-Point Double Indexed
3641*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3642*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3643*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3644*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3645	unsigned_word b;
3646	unsigned_word EA;
3647	if (RA_is_0) b = 0;
3648	else         b = *rA;
3649	EA = b + *rB;
3650	STORE(EA, 8, *frS);
3651	PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3652
36530.31,6.FRS,11.RA,16.RB,21.983,31./:X:f::Store Floating-Point Integer Word Indexed
3654*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3655*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3656*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3657	unsigned_word b;
3658	unsigned_word EA;
3659	if (RA_is_0) b = 0;
3660	else         b = *rA;
3661	EA = b + *rB;
3662	STORE(EA, 4, *frS);
3663	PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3664
36650.55,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double with Update
3666*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3667*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3668*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3669*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3670	unsigned_word EA;
3671	if (RA_is_0)
3672	  program_interrupt(processor, cia,
3673	                    illegal_instruction_program_interrupt);
3674	EA = *rA + EXTS(D);
3675	STORE(EA, 8, *frS);
3676	*rA = EA;
3677	PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3678
36790.31,6.FRS,11.RA,16.RB,21.759,31./:X:f::Store Floating-Point Double with Update Indexed
3680*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3681*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3682*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3683*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3684	unsigned_word EA;
3685	if (RA_is_0)
3686	  program_interrupt(processor, cia,
3687	                    illegal_instruction_program_interrupt);
3688	EA = *rA + *rB;
3689	STORE(EA, 8, *frS);
3690	*rA = EA;
3691	PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3692
3693
3694#
3695# I.4.6.4 Floating-Point Move Instructions
3696#
3697
36980.63,6.FRT,11./,16.FRB,21.72,31.Rc:X:f::Floating Move Register
3699*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3700*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3701*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3702*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3703	*frT = *frB;
3704	CR1_UPDATE(Rc);
3705	PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3706
37070.63,6.FRT,11./,16.FRB,21.40,31.Rc:X:f::Floating Negate
3708*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3709*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3710*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3711*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3712	*frT = *frB ^ BIT64(0);
3713	CR1_UPDATE(Rc);
3714	PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3715
37160.63,6.FRT,11./,16.FRB,21.264,31.Rc:X:f::Floating Absolute Value
3717*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3718*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3719*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3720*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3721	*frT = *frB & ~BIT64(0);
3722	CR1_UPDATE(Rc);
3723	PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3724
37250.63,6.FRT,11./,16.FRB,21.136,31.Rc:X:f::Floating Negative Absolute Value
3726*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3727*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3728*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3729*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3730	*frT = *frB | BIT64(0);
3731	CR1_UPDATE(Rc);
3732	PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3733
3734
3735#
3736# I.4.6.5 Floating-Point Arithmetic Instructions
3737#
3738
37390.63,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadd:Floating Add
3740*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3741*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3742*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3743*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3744	FPSCR_BEGIN;
3745	if (is_invalid_operation(processor, cia,
3746	                         *frA, *frB,
3747	                         fpscr_vxsnan | fpscr_vxisi,
3748	                         0, /*single?*/
3749	                         0) /*negate?*/) {
3750	  invalid_arithemetic_operation(processor, cia,
3751	                                frT, *frA, *frB, 0,
3752	                                0, /*instruction_is_frsp*/
3753	                                0, /*instruction_is_convert_to_64bit*/
3754	                                0, /*instruction_is_convert_to_32bit*/
3755	                                0); /*single-precision*/
3756	}
3757	else {
3758	  /*HACK!*/
3759	  double s = *(double*)frA + *(double*)frB;
3760	  *(double*)frT = s;
3761	}
3762	FPSCR_END(Rc);
3763	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3764
37650.59,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadds:Floating Add Single
3766*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3767*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3768*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3769*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3770	FPSCR_BEGIN;
3771	if (is_invalid_operation(processor, cia,
3772	                         *frA, *frB,
3773	                         fpscr_vxsnan | fpscr_vxisi,
3774	                         1, /*single?*/
3775	                         0) /*negate?*/) {
3776	  invalid_arithemetic_operation(processor, cia,
3777	                                frT, *frA, *frB, 0,
3778	                                0, /*instruction_is_frsp*/
3779	                                0, /*instruction_is_convert_to_64bit*/
3780	                                0, /*instruction_is_convert_to_32bit*/
3781	                                1); /*single-precision*/
3782	}
3783	else {
3784	  /*HACK!*/
3785	  float s = *(double*)frA + *(double*)frB;
3786	  *(double*)frT = s;
3787	}
3788	FPSCR_END(Rc);
3789	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3790
37910.63,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsub:Floating Subtract
3792*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3793*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3794*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3795*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3796	FPSCR_BEGIN;
3797	if (is_invalid_operation(processor, cia,
3798	                         *frA, *frB,
3799	                         fpscr_vxsnan | fpscr_vxisi,
3800	                         0, /*single?*/
3801	                         1) /*negate?*/) {
3802	  invalid_arithemetic_operation(processor, cia,
3803	                                frT, *frA, *frB, 0,
3804	                                0, /*instruction_is_frsp*/
3805	                                0, /*instruction_is_convert_to_64bit*/
3806	                                0, /*instruction_is_convert_to_32bit*/
3807	                                0); /*single-precision*/
3808	}
3809	else {
3810	  /*HACK!*/
3811	  double s = *(double*)frA - *(double*)frB;
3812	  *(double*)frT = s;
3813	}
3814	FPSCR_END(Rc);
3815	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3816
38170.59,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsubs:Floating Subtract Single
3818*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3819*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3820*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3821*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3822	FPSCR_BEGIN;
3823	if (is_invalid_operation(processor, cia,
3824	                         *frA, *frB,
3825	                         fpscr_vxsnan | fpscr_vxisi,
3826	                         1, /*single?*/
3827	                         1) /*negate?*/) {
3828	  invalid_arithemetic_operation(processor, cia,
3829	                                frT, *frA, *frB, 0,
3830	                                0, /*instruction_is_frsp*/
3831	                                0, /*instruction_is_convert_to_64bit*/
3832	                                0, /*instruction_is_convert_to_32bit*/
3833	                                1); /*single-precision*/
3834	}
3835	else {
3836	  /*HACK!*/
3837	  float s = *(double*)frA - *(double*)frB;
3838	  *(double*)frT = s;
3839	}
3840	FPSCR_END(Rc);
3841	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3842
38430.63,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmul:Floating Multiply
3844*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   5,  5,  0
3845*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
3846*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
3847*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3848	FPSCR_BEGIN;
3849	if (is_invalid_operation(processor, cia,
3850	                         *frA, *frC,
3851	                         fpscr_vxsnan | fpscr_vximz,
3852	                         0, /*single?*/
3853	                         0) /*negate?*/) {
3854	  invalid_arithemetic_operation(processor, cia,
3855	                                frT, *frA, 0, *frC,
3856	                                0, /*instruction_is_frsp*/
3857	                                0, /*instruction_is_convert_to_64bit*/
3858	                                0, /*instruction_is_convert_to_32bit*/
3859	                                0); /*single-precision*/
3860	}
3861	else {
3862	  /*HACK!*/
3863	  double s = *(double*)frA * *(double*)frC;
3864	  *(double*)frT = s;
3865	}
3866	FPSCR_END(Rc);
3867	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRC_BITMASK, Rc);
3868
38690.59,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmuls:Floating Multiply Single
3870*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3871*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3872*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3873*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3874	FPSCR_BEGIN;
3875	if (is_invalid_operation(processor, cia,
3876	                         *frA, *frC,
3877	                         fpscr_vxsnan | fpscr_vximz,
3878	                         1, /*single?*/
3879	                         0) /*negate?*/) {
3880	  invalid_arithemetic_operation(processor, cia,
3881	                                frT, *frA, 0, *frC,
3882	                                0, /*instruction_is_frsp*/
3883	                                0, /*instruction_is_convert_to_64bit*/
3884	                                0, /*instruction_is_convert_to_32bit*/
3885	                                1); /*single-precision*/
3886	}
3887	else {
3888	  /*HACK!*/
3889	  float s = *(double*)frA * *(double*)frC;
3890	  *(double*)frT = s;
3891	}
3892	FPSCR_END(Rc);
3893	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRC_BITMASK, Rc);
3894
38950.63,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdiv:Floating Divide
3896*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   31, 31, 0
3897*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   33, 33, 0
3898*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   33, 33, 0
3899*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   32, 32, 0
3900	FPSCR_BEGIN;
3901	if (is_invalid_operation(processor, cia,
3902	                         *frA, *frB,
3903	                         fpscr_vxsnan | fpscr_vxzdz,
3904	                         0, /*single?*/
3905	                         0) /*negate?*/) {
3906	  invalid_arithemetic_operation(processor, cia,
3907	                                frT, *frA, *frB, 0,
3908	                                0, /*instruction_is_frsp*/
3909	                                0, /*instruction_is_convert_to_64bit*/
3910	                                0, /*instruction_is_convert_to_32bit*/
3911	                                0); /*single-precision*/
3912	}
3913	else if (is_invalid_zero_divide (processor, cia,
3914	                                 *frA, *frB,
3915	                                 0 /*single?*/)) {
3916	  invalid_zero_divide_operation (processor, cia,
3917	                                 frT, *frA, *frB,
3918	                                 0 /*single?*/);
3919	}
3920	else {
3921	  /*HACK!*/
3922	  double s = *(double*)frA / *(double*)frB;
3923	  *(double*)frT = s;
3924	}
3925	FPSCR_END(Rc);
3926	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3927
39280.59,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdivs:Floating Divide Single
3929*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   17, 17, 0
3930*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   18, 18, 0
3931*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   18, 18, 0
3932*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   18, 18, 0
3933	FPSCR_BEGIN;
3934	if (is_invalid_operation(processor, cia,
3935	                         *frA, *frB,
3936	                         fpscr_vxsnan | fpscr_vxzdz,
3937	                         1, /*single?*/
3938	                         0) /*negate?*/) {
3939	  invalid_arithemetic_operation(processor, cia,
3940	                                frT, *frA, *frB, 0,
3941	                                0, /*instruction_is_frsp*/
3942	                                0, /*instruction_is_convert_to_64bit*/
3943	                                0, /*instruction_is_convert_to_32bit*/
3944	                                1); /*single-precision*/
3945	}
3946	else if (is_invalid_zero_divide (processor, cia,
3947	                                 *frA, *frB,
3948	                                 1 /*single?*/)) {
3949	  invalid_zero_divide_operation (processor, cia,
3950	                                 frT, *frA, *frB,
3951	                                 1 /*single?*/);
3952	}
3953	else {
3954	  /*HACK!*/
3955	  float s = *(double*)frA / *(double*)frB;
3956	  *(double*)frT = s;
3957	}
3958	FPSCR_END(Rc);
3959	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3960
39610.63,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f:fmadd:Floating Multiply-Add
3962*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   5,  5,  0
3963*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
3964*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
3965*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3966	FPSCR_BEGIN;
3967	double product; /*HACK! - incorrectly loosing precision ... */
3968	/* compute the multiply */
3969	if (is_invalid_operation(processor, cia,
3970	                         *frA, *frC,
3971	                         fpscr_vxsnan | fpscr_vximz,
3972	                         0, /*single?*/
3973	                         0) /*negate?*/) {
3974	  union { double d; uint64_t u; } tmp;
3975	  invalid_arithemetic_operation(processor, cia,
3976	                                &tmp.u, *frA, 0, *frC,
3977	                                0, /*instruction_is_frsp*/
3978	                                0, /*instruction_is_convert_to_64bit*/
3979	                                0, /*instruction_is_convert_to_32bit*/
3980	                                0); /*single-precision*/
3981	  product = tmp.d;
3982	}
3983	else {
3984	  /*HACK!*/
3985	  product = *(double*)frA * *(double*)frC;
3986	}
3987	/* compute the add */
3988	if (is_invalid_operation(processor, cia,
3989	                         product, *frB,
3990	                         fpscr_vxsnan | fpscr_vxisi,
3991	                         0, /*single?*/
3992	                         0) /*negate?*/) {
3993	  invalid_arithemetic_operation(processor, cia,
3994	                                frT, product, *frB, 0,
3995	                                0, /*instruction_is_frsp*/
3996	                                0, /*instruction_is_convert_to_64bit*/
3997	                                0, /*instruction_is_convert_to_32bit*/
3998	                                0); /*single-precision*/
3999	}
4000	else {
4001	  /*HACK!*/
4002	  double s = product + *(double*)frB;
4003	  *(double*)frT = s;
4004	}
4005	FPSCR_END(Rc);
4006	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4007
40080.59,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f::Floating Multiply-Add Single
4009*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
4010*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4011*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4012*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4013	FPSCR_BEGIN;
4014	float product; /*HACK! - incorrectly loosing precision ... */
4015	/* compute the multiply */
4016	if (is_invalid_operation(processor, cia,
4017	                         *frA, *frC,
4018	                         fpscr_vxsnan | fpscr_vximz,
4019	                         1, /*single?*/
4020	                         0) /*negate?*/) {
4021	  union { double d; uint64_t u; } tmp;
4022	  invalid_arithemetic_operation(processor, cia,
4023	                                &tmp.u, *frA, 0, *frC,
4024	                                0, /*instruction_is_frsp*/
4025	                                0, /*instruction_is_convert_to_64bit*/
4026	                                0, /*instruction_is_convert_to_32bit*/
4027	                                0); /*single-precision*/
4028	  product = tmp.d;
4029	}
4030	else {
4031	  /*HACK!*/
4032	  product = *(double*)frA * *(double*)frC;
4033	}
4034	/* compute the add */
4035	if (is_invalid_operation(processor, cia,
4036	                         product, *frB,
4037	                         fpscr_vxsnan | fpscr_vxisi,
4038	                         1, /*single?*/
4039	                         0) /*negate?*/) {
4040	  invalid_arithemetic_operation(processor, cia,
4041	                                frT, product, *frB, 0,
4042	                                0, /*instruction_is_frsp*/
4043	                                0, /*instruction_is_convert_to_64bit*/
4044	                                0, /*instruction_is_convert_to_32bit*/
4045	                                0); /*single-precision*/
4046	}
4047	else {
4048	  /*HACK!*/
4049	  float s = product + *(double*)frB;
4050	  *(double*)frT = (double)s;
4051	}
4052	FPSCR_END(Rc);
4053	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4054
40550.63,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract
4056*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   5,  5,  0
4057*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
4058*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
4059*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4060	FPSCR_BEGIN;
4061	double product; /*HACK! - incorrectly loosing precision ... */
4062	/* compute the multiply */
4063	if (is_invalid_operation(processor, cia,
4064	                         *frA, *frC,
4065	                         fpscr_vxsnan | fpscr_vximz,
4066	                         0, /*single?*/
4067	                         0) /*negate?*/) {
4068	  union { double d; uint64_t u; } tmp;
4069	  invalid_arithemetic_operation(processor, cia,
4070	                                &tmp.u, *frA, 0, *frC,
4071	                                0, /*instruction_is_frsp*/
4072	                                0, /*instruction_is_convert_to_64bit*/
4073	                                0, /*instruction_is_convert_to_32bit*/
4074	                                0); /*single-precision*/
4075	  product = tmp.d;
4076	}
4077	else {
4078	  /*HACK!*/
4079	  product = *(double*)frA * *(double*)frC;
4080	}
4081	/* compute the subtract */
4082	if (is_invalid_operation(processor, cia,
4083	                         product, *frB,
4084	                         fpscr_vxsnan | fpscr_vxisi,
4085	                         0, /*single?*/
4086	                         0) /*negate?*/) {
4087	  invalid_arithemetic_operation(processor, cia,
4088	                                frT, product, *frB, 0,
4089	                                0, /*instruction_is_frsp*/
4090	                                0, /*instruction_is_convert_to_64bit*/
4091	                                0, /*instruction_is_convert_to_32bit*/
4092	                                0); /*single-precision*/
4093	}
4094	else {
4095	  /*HACK!*/
4096	  double s = product - *(double*)frB;
4097	  *(double*)frT = s;
4098	}
4099	FPSCR_END(Rc);
4100	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4101
41020.59,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract Single
4103*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
4104*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4105*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4106*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4107	FPSCR_BEGIN;
4108	float product; /*HACK! - incorrectly loosing precision ... */
4109	/* compute the multiply */
4110	if (is_invalid_operation(processor, cia,
4111	                         *frA, *frC,
4112	                         fpscr_vxsnan | fpscr_vximz,
4113	                         1, /*single?*/
4114	                         0) /*negate?*/) {
4115	  union { double d; uint64_t u; } tmp;
4116	  invalid_arithemetic_operation(processor, cia,
4117	                                &tmp.u, *frA, 0, *frC,
4118	                                0, /*instruction_is_frsp*/
4119	                                0, /*instruction_is_convert_to_64bit*/
4120	                                0, /*instruction_is_convert_to_32bit*/
4121	                                0); /*single-precision*/
4122	  product = tmp.d;
4123	}
4124	else {
4125	  /*HACK!*/
4126	  product = *(double*)frA * *(double*)frC;
4127	}
4128	/* compute the subtract */
4129	if (is_invalid_operation(processor, cia,
4130	                         product, *frB,
4131	                         fpscr_vxsnan | fpscr_vxisi,
4132	                         1, /*single?*/
4133	                         0) /*negate?*/) {
4134	  invalid_arithemetic_operation(processor, cia,
4135	                                frT, product, *frB, 0,
4136	                                0, /*instruction_is_frsp*/
4137	                                0, /*instruction_is_convert_to_64bit*/
4138	                                0, /*instruction_is_convert_to_32bit*/
4139	                                0); /*single-precision*/
4140	}
4141	else {
4142	  /*HACK!*/
4143	  float s = product - *(double*)frB;
4144	  *(double*)frT = (double)s;
4145	}
4146	FPSCR_END(Rc);
4147	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4148
41490.63,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add
4150*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   5,  5,  0
4151*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
4152*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
4153*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4154	FPSCR_BEGIN;
4155	double product; /*HACK! - incorrectly loosing precision ... */
4156	/* compute the multiply */
4157	if (is_invalid_operation(processor, cia,
4158	                         *frA, *frC,
4159	                         fpscr_vxsnan | fpscr_vximz,
4160	                         0, /*single?*/
4161	                         0) /*negate?*/) {
4162	  union { double d; uint64_t u; } tmp;
4163	  invalid_arithemetic_operation(processor, cia,
4164	                                &tmp.u, *frA, 0, *frC,
4165	                                0, /*instruction_is_frsp*/
4166	                                0, /*instruction_is_convert_to_64bit*/
4167	                                0, /*instruction_is_convert_to_32bit*/
4168	                                0); /*single-precision*/
4169	  product = tmp.d;
4170	}
4171	else {
4172	  /*HACK!*/
4173	  product = *(double*)frA * *(double*)frC;
4174	}
4175	/* compute the add */
4176	if (is_invalid_operation(processor, cia,
4177	                         product, *frB,
4178	                         fpscr_vxsnan | fpscr_vxisi,
4179	                         0, /*single?*/
4180	                         0) /*negate?*/) {
4181	  invalid_arithemetic_operation(processor, cia,
4182	                                frT, product, *frB, 0,
4183	                                0, /*instruction_is_frsp*/
4184	                                0, /*instruction_is_convert_to_64bit*/
4185	                                0, /*instruction_is_convert_to_32bit*/
4186	                                0); /*single-precision*/
4187	}
4188	else {
4189	  /*HACK!*/
4190	  double s = -(product + *(double*)frB);
4191	  *(double*)frT = s;
4192	}
4193	FPSCR_END(Rc);
4194	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4195
41960.59,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add Single
4197*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
4198*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4199*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4200*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4201	FPSCR_BEGIN;
4202	float product; /*HACK! - incorrectly loosing precision ... */
4203	/* compute the multiply */
4204	if (is_invalid_operation(processor, cia,
4205	                         *frA, *frC,
4206	                         fpscr_vxsnan | fpscr_vximz,
4207	                         1, /*single?*/
4208	                         0) /*negate?*/) {
4209	  union { double d; uint64_t u; } tmp;
4210	  invalid_arithemetic_operation(processor, cia,
4211	                                &tmp.u, *frA, 0, *frC,
4212	                                0, /*instruction_is_frsp*/
4213	                                0, /*instruction_is_convert_to_64bit*/
4214	                                0, /*instruction_is_convert_to_32bit*/
4215	                                0); /*single-precision*/
4216	  product = tmp.d;
4217	}
4218	else {
4219	  /*HACK!*/
4220	  product = *(double*)frA * *(double*)frC;
4221	}
4222	/* compute the add */
4223	if (is_invalid_operation(processor, cia,
4224	                         product, *frB,
4225	                         fpscr_vxsnan | fpscr_vxisi,
4226	                         1, /*single?*/
4227	                         0) /*negate?*/) {
4228	  invalid_arithemetic_operation(processor, cia,
4229	                                frT, product, *frB, 0,
4230	                                0, /*instruction_is_frsp*/
4231	                                0, /*instruction_is_convert_to_64bit*/
4232	                                0, /*instruction_is_convert_to_32bit*/
4233	                                0); /*single-precision*/
4234	}
4235	else {
4236	  /*HACK!*/
4237	  float s = -(product + *(double*)frB);
4238	  *(double*)frT = (double)s;
4239	}
4240	FPSCR_END(Rc);
4241	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4242
42430.63,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract
4244*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   5,  5,  0
4245*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
4246*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
4247*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4248	FPSCR_BEGIN;
4249	double product; /*HACK! - incorrectly loosing precision ... */
4250	/* compute the multiply */
4251	if (is_invalid_operation(processor, cia,
4252	                         *frA, *frC,
4253	                         fpscr_vxsnan | fpscr_vximz,
4254	                         0, /*single?*/
4255	                         0) /*negate?*/) {
4256	  union { double d; uint64_t u; } tmp;
4257	  invalid_arithemetic_operation(processor, cia,
4258	                                &tmp.u, *frA, 0, *frC,
4259	                                0, /*instruction_is_frsp*/
4260	                                0, /*instruction_is_convert_to_64bit*/
4261	                                0, /*instruction_is_convert_to_32bit*/
4262	                                0); /*single-precision*/
4263	  product = tmp.d;
4264	}
4265	else {
4266	  /*HACK!*/
4267	  product = *(double*)frA * *(double*)frC;
4268	}
4269	/* compute the subtract */
4270	if (is_invalid_operation(processor, cia,
4271	                         product, *frB,
4272	                         fpscr_vxsnan | fpscr_vxisi,
4273	                         0, /*single?*/
4274	                         0) /*negate?*/) {
4275	  invalid_arithemetic_operation(processor, cia,
4276	                                frT, product, *frB, 0,
4277	                                0, /*instruction_is_frsp*/
4278	                                0, /*instruction_is_convert_to_64bit*/
4279	                                0, /*instruction_is_convert_to_32bit*/
4280	                                0); /*single-precision*/
4281	}
4282	else {
4283	  /*HACK!*/
4284	  double s = -(product - *(double*)frB);
4285	  *(double*)frT = s;
4286	}
4287	FPSCR_END(Rc);
4288	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4289
42900.59,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract Single
4291*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
4292*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4293*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4294*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4295	FPSCR_BEGIN;
4296	float product; /*HACK! - incorrectly loosing precision ... */
4297	/* compute the multiply */
4298	if (is_invalid_operation(processor, cia,
4299	                         *frA, *frC,
4300	                         fpscr_vxsnan | fpscr_vximz,
4301	                         1, /*single?*/
4302	                         0) /*negate?*/) {
4303	  union { double d; uint64_t u; } tmp;
4304	  invalid_arithemetic_operation(processor, cia,
4305	                                &tmp.u, *frA, 0, *frC,
4306	                                0, /*instruction_is_frsp*/
4307	                                0, /*instruction_is_convert_to_64bit*/
4308	                                0, /*instruction_is_convert_to_32bit*/
4309	                                0); /*single-precision*/
4310	  product = tmp.d;
4311	}
4312	else {
4313	  /*HACK!*/
4314	  product = *(double*)frA * *(double*)frC;
4315	}
4316	/* compute the subtract */
4317	if (is_invalid_operation(processor, cia,
4318	                         product, *frB,
4319	                         fpscr_vxsnan | fpscr_vxisi,
4320	                         1, /*single?*/
4321	                         0) /*negate?*/) {
4322	  invalid_arithemetic_operation(processor, cia,
4323	                                frT, product, *frB, 0,
4324	                                0, /*instruction_is_frsp*/
4325	                                0, /*instruction_is_convert_to_64bit*/
4326	                                0, /*instruction_is_convert_to_32bit*/
4327	                                0); /*single-precision*/
4328	}
4329	else {
4330	  /*HACK!*/
4331	  float s = -(product - *(double*)frB);
4332	  *(double*)frT = (double)s;
4333	}
4334	FPSCR_END(Rc);
4335	PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4336
4337
4338#
4339# I.4.6.6 Floating-Point Rounding and Conversion Instructions
4340#
4341
43420.63,6.FRT,11./,16.FRB,21.12,31.Rc:X:f::Floating Round to Single-Precision
4343*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
4344*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4345*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4346*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4347	int sign;
4348	int exp;
4349	uint64_t frac_grx;
4350	/***/
4351	  /* split off cases for what to do */
4352	  if (EXTRACTED64(*frB, 1, 11) < 897
4353	      && EXTRACTED64(*frB, 1, 63) > 0) {
4354	      if ((FPSCR & fpscr_ue) == 0) GOTO(Disabled_Exponent_Underflow);
4355	      if ((FPSCR & fpscr_ue) != 0) GOTO(Enabled_Exponent_Underflow);
4356	  }
4357	  if (EXTRACTED64(*frB, 1, 11) > 1150
4358	      && EXTRACTED64(*frB, 1, 11) < 2047) {
4359	      if ((FPSCR & fpscr_oe) == 0) GOTO(Disabled_Exponent_Overflow);
4360	      if ((FPSCR & fpscr_oe) != 0) GOTO(Enabled_Exponent_Overflow);
4361	  }
4362	  if (EXTRACTED64(*frB, 1, 11) > 896
4363	      && EXTRACTED64(*frB, 1, 11) < 1151) GOTO(Normal_Operand);
4364	  if (EXTRACTED64(*frB, 1, 63) == 0) GOTO(Zero_Operand);
4365	  if (EXTRACTED64(*frB, 1, 11) == 2047) {
4366	    if (EXTRACTED64(*frB, 12, 63) == 0) GOTO(Infinity_Operand);
4367	    if (EXTRACTED64(*frB, 12, 12) == 1) GOTO(QNaN_Operand);
4368	    if (EXTRACTED64(*frB, 12, 12) == 0
4369	        && EXTRACTED64(*frB, 13, 63) > 0) GOTO(SNaN_Operand);
4370	  }
4371	/**/
4372	LABEL(Disabled_Exponent_Underflow):
4373	  sign = EXTRACTED64(*frB, 0, 0);
4374	  if (EXTRACTED64(*frB, 1, 11) == 0) {
4375	    exp = -1022;
4376	    frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4377	  }
4378	  if (EXTRACTED64(*frB, 1, 11) > 0) {
4379	    exp = EXTRACTED64(*frB, 1, 11) - 1023;
4380	    frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4381	  }
4382	    /* G|R|X == zero from above */
4383	    while (exp < -126) {
4384	      exp = exp + 1;
4385	      frac_grx = (INSERTED64(EXTRACTED64(frac_grx, 0, 54), 1, 55)
4386	                  | MASKED64(frac_grx, 55, 55));
4387	    }
4388	  FPSCR_SET_UX(EXTRACTED64(frac_grx, 24, 55) > 0);
4389	  Round_Single(processor, sign, &exp, &frac_grx);
4390	  FPSCR_SET_XX(FPSCR & fpscr_fi);
4391	  if (EXTRACTED64(frac_grx, 0, 52) == 0) {
4392	    *frT = INSERTED64(sign, 0, 0);
4393	    if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
4394	    if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
4395	  }
4396	  if (EXTRACTED64(frac_grx, 0, 52) > 0) {
4397	    if (EXTRACTED64(frac_grx, 0, 0) == 1) {
4398	      if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4399	      if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4400	    }
4401	    if (EXTRACTED64(frac_grx, 0, 0) == 0) {
4402	      if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_denormalized_number);
4403	      if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_denormalized_number);
4404	    }
4405	    /*Normalize_Operand:*/
4406	      while (EXTRACTED64(frac_grx, 0, 0) == 0) {
4407	        exp = exp - 1;
4408	        frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1,  52), 0, 51);
4409	      }
4410	    *frT = (INSERTED64(sign, 0, 0)
4411	            | INSERTED64(exp + 1023, 1, 11)
4412	            | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4413	  }
4414	  GOTO(Done);
4415	/**/
4416	LABEL(Enabled_Exponent_Underflow):
4417	  FPSCR_SET_UX(1);
4418	  sign = EXTRACTED64(*frB, 0, 0);
4419	  if (EXTRACTED64(*frB, 1, 11) == 0) {
4420	    exp = -1022;
4421	    frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4422	  }
4423	  if (EXTRACTED64(*frB, 1, 11) > 0) {
4424	    exp = EXTRACTED64(*frB, 1, 11) - 1023;
4425	    frac_grx = (BIT64(0) |
4426	                INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52));
4427	  }
4428	  /*Normalize_Operand:*/
4429	    while (EXTRACTED64(frac_grx, 0, 0) == 0) {
4430	      exp = exp - 1;
4431	      frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1, 52), 0, 51);
4432	    }
4433	  Round_Single(processor, sign, &exp, &frac_grx);
4434	  FPSCR_SET_XX(FPSCR & fpscr_fi);
4435	  exp = exp + 192;
4436	  *frT = (INSERTED64(sign, 0, 0)
4437	          | INSERTED64(exp + 1023, 1, 11)
4438	          | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4439	  if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4440	  if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4441	  GOTO(Done);
4442	/**/
4443	LABEL(Disabled_Exponent_Overflow):
4444	  FPSCR_SET_OX(1);
4445	  if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
4446	    if (EXTRACTED64(*frB, 0, 0) == 0) {
4447	      *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
4448	      FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
4449	    }
4450	    if (EXTRACTED64(*frB, 0, 0) == 1) {
4451	      *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
4452	      FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
4453	    }
4454	  }
4455	  if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_zero) {
4456	    if (EXTRACTED64(*frB, 0, 0) == 0) {
4457	      *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
4458	      FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4459	    }
4460	    if (EXTRACTED64(*frB, 0, 0) == 1) {
4461	      *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
4462	      FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4463	    }
4464	  }
4465	  if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_pos_infinity) {
4466	    if (EXTRACTED64(*frB, 0, 0) == 0) {
4467	      *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
4468	      FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
4469	    }
4470	    if (EXTRACTED64(*frB, 0, 0) == 1) {
4471	      *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
4472	      FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4473	    }
4474	  }
4475	  if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_neg_infinity) {
4476	    if (EXTRACTED64(*frB, 0, 0) == 0) {
4477	      *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
4478	      FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4479	    }
4480	    if (EXTRACTED64(*frB, 0, 0) == 1) {
4481	      *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
4482	      FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
4483	    }
4484	  }
4485	  /* FPSCR[FR] <- undefined */
4486	  FPSCR_SET_FI(1);
4487	  FPSCR_SET_XX(1);
4488	  GOTO(Done);
4489	/**/
4490	LABEL(Enabled_Exponent_Overflow):
4491	  sign = EXTRACTED64(*frB, 0, 0);
4492	  exp = EXTRACTED64(*frB, 1, 11) - 1023;
4493	  frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4494	  Round_Single(processor, sign, &exp, &frac_grx);
4495	  FPSCR_SET_XX(FPSCR & fpscr_fi);
4496	/**/
4497	LABEL(Enabled_Overflow):
4498	  FPSCR_SET_OX(1);
4499	  exp = exp - 192;
4500	  *frT = (INSERTED64(sign, 0, 0)
4501	          | INSERTED64(exp + 1023, 1, 11)
4502	          | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4503	  if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4504	  if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4505	  GOTO(Done);
4506	/**/
4507	LABEL(Zero_Operand):
4508	  *frT = *frB;
4509	  if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
4510	  if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
4511	  FPSCR_SET_FR(0);
4512	  FPSCR_SET_FI(0);
4513	  GOTO(Done);
4514	/**/
4515	LABEL(Infinity_Operand):
4516	  *frT = *frB;
4517	  if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
4518	  if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
4519	  FPSCR_SET_FR(0);
4520	  FPSCR_SET_FI(0);
4521	  GOTO(Done);
4522	/**/
4523	LABEL(QNaN_Operand):
4524	  *frT = INSERTED64(EXTRACTED64(*frB, 0, 34), 0, 34);
4525	  FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
4526	  FPSCR_SET_FR(0);
4527	  FPSCR_SET_FI(0);
4528	  GOTO(Done);
4529	/**/
4530	LABEL(SNaN_Operand):
4531	  FPSCR_OR_VX(fpscr_vxsnan);
4532	  if ((FPSCR & fpscr_ve) == 0) {
4533	    *frT = (MASKED64(*frB, 0, 11)
4534	            | BIT64(12)
4535	            | MASKED64(*frB, 13, 34));
4536	    FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
4537	  }
4538	  FPSCR_SET_FR(0);
4539	  FPSCR_SET_FI(0);
4540	  GOTO(Done);
4541	/**/
4542	LABEL(Normal_Operand):
4543	  sign = EXTRACTED64(*frB, 0, 0);
4544	  exp = EXTRACTED64(*frB, 1, 11) - 1023;
4545	  frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4546	  Round_Single(processor, sign, &exp, &frac_grx);
4547	  FPSCR_SET_XX(FPSCR & fpscr_fi);
4548	  if (exp > 127 && (FPSCR & fpscr_oe) == 0) GOTO(Disabled_Exponent_Overflow);
4549	  if (exp > 127 && (FPSCR & fpscr_oe) != 0) GOTO(Enabled_Overflow);
4550	  *frT = (INSERTED64(sign, 0, 0)
4551	          | INSERTED64(exp + 1023, 1, 11)
4552	          | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4553	  if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4554	  if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4555	  GOTO(Done);
4556	/**/
4557	LABEL(Done):
4558	  PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
4559
4560
45610.63,6.FRT,11./,16.FRB,21.814,31.Rc:X:64,f::Floating Convert To Integer Doubleword
4562	floating_point_assist_interrupt(processor, cia);
4563
45640.63,6.FRT,11./,16.FRB,21.815,31.Rc:X:64,f::Floating Convert To Integer Doubleword with round towards Zero
4565	floating_point_assist_interrupt(processor, cia);
4566
45670.63,6.FRT,11./,16.FRB,21.14,31.Rc:X:f::Floating Convert To Integer Word
4568	floating_point_assist_interrupt(processor, cia);
4569
45700.63,6.FRT,11./,16.FRB,21.15,31.Rc:X:f:fctiwz:Floating Convert To Integer Word with round towards Zero
4571*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
4572*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4573*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4574*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4575	FPSCR_BEGIN;
4576	convert_to_integer(processor, cia,
4577	                   frT, *frB,
4578	                   fpscr_rn_round_towards_zero, 32);
4579	FPSCR_END(Rc);
4580	PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
4581
45820.63,6.FRT,11./,16.FRB,21.846,31.Rc:X:64,f::Floating Convert from Integer Doubleword
4583	int sign = EXTRACTED64(*frB, 0, 0);
4584	int exp = 63;
4585	uint64_t frac = *frB;
4586	/***/
4587	  if (frac == 0) GOTO(Zero_Operand);
4588	  if (sign == 1) frac = ~frac + 1;
4589	  while (EXTRACTED64(frac, 0, 0) == 0) {
4590	    /*??? do the loop 0 times if (FRB) = max negative integer */
4591	    frac = INSERTED64(EXTRACTED64(frac, 1, 63), 0, 62);
4592	    exp = exp - 1;
4593	  }
4594	  Round_Float(processor, sign, &exp, &frac, FPSCR & fpscr_rn);
4595	  if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4596	  if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4597	  *frT = (INSERTED64(sign, 0, 0)
4598	          | INSERTED64(exp + 1023, 1, 11)
4599	          | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
4600	  GOTO(Done);
4601	/**/
4602	LABEL(Zero_Operand):
4603	  FPSCR_SET_FR(0);
4604	  FPSCR_SET_FI(0);
4605	  FPSCR_SET_FPRF(fpscr_rf_pos_zero);
4606	  *frT = 0;
4607	  GOTO(Done);
4608	/**/
4609	LABEL(Done):
4610	  PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
4611
4612
4613#
4614# I.4.6.7 Floating-Point Compare Instructions
4615#
4616
46170.63,6.BF,9./,11.FRA,16.FRB,21.0,31./:X:f:fcmpu:Floating Compare Unordered
4618*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
4619*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4620*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4621*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4622	FPSCR_BEGIN;
4623	unsigned c;
4624	if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
4625	  c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
4626	else if (is_less_than(frA, frB))
4627	  c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
4628	else if (is_greater_than(frA, frB))
4629	  c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
4630	else
4631	  c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
4632	FPSCR_SET_FPCC(c);
4633	CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
4634	if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0))
4635	  FPSCR_OR_VX(fpscr_vxsnan);
4636	FPSCR_END(0);
4637	PPC_INSN_FLOAT_CR(0, FRA_BITMASK | FRB_BITMASK, BF_BITMASK);
4638
46390.63,6.BF,9./,11.FRA,16.FRB,21.32,31./:X:f:fcmpo:Floating Compare Ordered
4640*601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
4641*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4642*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4643*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4644	FPSCR_BEGIN;
4645	unsigned c;
4646	if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
4647	  c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
4648	else if (is_less_than(frA, frB))
4649	  c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
4650	else if (is_greater_than(frA, frB))
4651	  c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
4652	else
4653	  c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
4654	FPSCR_SET_FPCC(c);
4655	CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
4656	if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0)) {
4657	  FPSCR_OR_VX(fpscr_vxsnan);
4658	  if ((FPSCR & fpscr_ve) == 0)
4659	    FPSCR_OR_VX(fpscr_vxvc);
4660	}
4661	else if (is_QNaN(*frA, 0) || is_QNaN(*frB, 0)) {
4662	  FPSCR_OR_VX(fpscr_vxvc);
4663	}
4664	FPSCR_END(0);
4665	PPC_INSN_FLOAT_CR(0, FRA_BITMASK | FRB_BITMASK, BF_BITMASK);
4666
4667
4668#
4669# I.4.6.8 Floating-Point Status and Control Register Instructions
4670#
4671
46720.63,6.FRT,11./,16./,21.583,31.Rc:X:f::Move From FPSCR
4673	FPSCR_BEGIN;
4674	*frT = FPSCR;
4675	FPSCR_END(Rc);
4676
46770.63,6.BF,9./,11.BFA,14./,16./,21.64,31./:X:f::Move to Condition Register from FPSCR
4678	FPSCR_BEGIN;
4679	unsigned field = FPSCR_FIELD(BFA);
4680	CR_SET(BF, field);
4681	FPSCR_SET(BFA, 0); /* FPSCR_END fixes up FEX/VX */
4682	FPSCR_END(0);
4683
46840.63,6.BF,9./,11./,16.U,20./,21.134,31.Rc:X:f::Move To FPSCR Field Immediate
4685	FPSCR_BEGIN;
4686	FPSCR_SET(BF, U);
4687	FPSCR_END(Rc);
4688
46890.63,6./,7.FLM,15./,16.FRB,21.711,31.Rc:XFL:f::Move To FPSCR Fields
4690	FPSCR_BEGIN;
4691	int i;
4692	for (i = 0; i < 8; i++) {
4693	  if ((FLM & BIT8(i))) {
4694	    FPSCR &= ~MASK32(i*4, i*4+3);
4695	    FPSCR |= MASKED32(*frB, i*4, i*4+3);
4696	  }
4697	}
4698	FPSCR_END(Rc);
4699
47000.63,6.BT,11./,16./,21.70,31.Rc:X:f::Move To FPSCR Bit 0
4701	FPSCR_BEGIN;
4702	uint32_t bit = BIT32(BT);
4703	FPSCR &= ~bit;
4704	FPSCR_END(Rc);
4705
47060.63,6.BT,11./,16./,21.38,31.Rc:X:f::Move To FPSCR Bit 1
4707	FPSCR_BEGIN;
4708	uint32_t bit = BIT32(BT);
4709	if (bit & fpscr_fi)
4710	  bit |= fpscr_xx;
4711	if ((bit & fpscr_vx_bits))
4712	  bit |= fpscr_fx;
4713	/* note - omit vx bit */
4714	if ((bit & (fpscr_ox | fpscr_ux | fpscr_zx | fpscr_xx)))
4715	  bit |= fpscr_fx;
4716	FPSCR |= bit;
4717	FPSCR_END(Rc);
4718
4719#
4720# I.A.1.2 Floating-Point Arithmetic Instructions
4721#
4722
47230.63,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f,o::Floating Square Root
4724	program_interrupt(processor, cia, optional_instruction_program_interrupt);
4725
47260.59,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f,o::Floating Square Root Single
4727	program_interrupt(processor, cia, optional_instruction_program_interrupt);
4728
47290.59,6.FRT,11./,16.FRB,21./,26.24,31.Rc:A:f,o::Floating Reciprocal Estimate Single
4730	program_interrupt(processor, cia, optional_instruction_program_interrupt);
4731
47320.63,6.FRT,11./,16.FRB,21./,26.26,31.Rc:A:f,o::Floating Reciprocal Square Root Estimate
4733	program_interrupt(processor, cia, optional_instruction_program_interrupt);
4734
4735#
4736# I.A.1.3 Floating-Point Select Instruction
4737#
4738
47390.63,6.FRT,11.FRA,16.FRB,21.FRC,26.23,31.Rc:A:f,o::Floating Select
4740*601: PPC_UNIT_BAD,   PPC_UNIT_BAD,   0,  0,  0
4741*603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4742*603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4743*604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
4744	if (CURRENT_MODEL == MODEL_ppc601) {
4745	  program_interrupt(processor, cia, optional_instruction_program_interrupt);
4746	} else {
4747	  uint64_t zero = 0;
4748	  FPSCR_BEGIN;
4749	  if (is_NaN(*frA, 0) || is_less_than (frA, &zero)) *frT = *frB;
4750	  else						    *frT = *frC;
4751	  FPSCR_END(Rc);
4752	  PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4753	}
4754
4755#
4756# II.3.2 Cache Management Instructions
4757#
4758
47590.31,6./,11.RA,16.RB,21.982,31./:X::icbi:Instruction Cache Block Invalidate
4760*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4761*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
4762*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
4763*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  1,  0
4764	/* blindly flush all instruction cache entries */
4765	#if WITH_IDECODE_CACHE_SIZE
4766	cpu_flush_icache(processor);
4767	#endif
4768	PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0);
4769
47700.19,6./,11./,16./,21.150,31./:XL::isync:Instruction Synchronize
4771*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4772*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
4773*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
4774*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  1,  0
4775	cpu_synchronize_context(processor, cia);
4776	PPC_INSN_INT(0, 0, 0);
4777
4778
4779#
4780# II.3.2.2 Data Cache Instructions
4781#
4782
47830.31,6./,11.RA,16.RB,21.278,31./:X:::Data Cache Block Touch
4784*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4785*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   2,  2,  0
4786*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   2,  2,  0
4787*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  1,  0
4788	TRACE(trace_tbd,("Data Cache Block Touch\n"));
4789	PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4790
47910.31,6./,11.RA,16.RB,21.246,31./:X:::Data Cache Block Touch for Store
4792*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4793*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   2,  2,  0
4794*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   2,  2,  0
4795*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
4796	TRACE(trace_tbd,("Data Cache Block Touch for Store\n"));
4797	PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4798
47990.31,6./,11.RA,16.RB,21.1014,31./:X:::Data Cache Block set to Zero
4800*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4801*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   10, 10, 0
4802*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   10, 10, 0
4803*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
4804	TRACE(trace_tbd,("Data Cache Block set to Zero\n"));
4805	PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4806
48070.31,6./,11.RA,16.RB,21.54,31./:X:::Data Cache Block Store
4808*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4809*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   5,  5,  0
4810*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   5,  5,  0
4811*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  1,  0
4812	TRACE(trace_tbd,("Data Cache Block Store\n"));
4813	PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4814
48150.31,6./,11.RA,16.RB,21.86,31./:X:::Data Cache Block Flush
4816*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4817*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   5,  5,  0
4818*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   5,  5,  0
4819*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  1,  0
4820	TRACE(trace_tbd,("Data Cache Block Flush\n"));
4821	PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4822
4823#
4824# II.3.3 Enforce In-order Execution of I/O Instruction
4825#
4826
48270.31,6./,11./,16./,21.854,31./:X::eieio:Enforce In-order Execution of I/O
4828	/* Since this model has no instruction overlap
4829	   this instruction need do nothing */
4830
4831#
4832# II.4.1 Time Base Instructions
4833#
4834
48350.31,6.RT,11.tbr,21.371,31./:XFX::mftb:Move From Time Base
4836*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
4837*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
4838*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  3,  3,  0
4839	int n = (tbr{5:9} << 5) | tbr{0:4};
4840	if (n == 268) {
4841	  if (is_64bit_implementation) *rT = TB;
4842	  else                         *rT = EXTRACTED64(TB, 32, 63);
4843	}
4844	else if (n == 269) {
4845	  if (is_64bit_implementation) *rT = EXTRACTED64(TB, 0, 31);
4846	  else                         *rT = EXTRACTED64(TB, 0, 31);
4847	}
4848	else
4849	  program_interrupt(processor, cia,
4850	                    illegal_instruction_program_interrupt);
4851
4852
4853#
4854# III.2.3.1 System Linkage Instructions
4855#
4856
48570.19,6./,11./,16./,21.50,31./:XL::rfi:Return From Interrupt
4858*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4859*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   3,  3,  0
4860*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   3,  3,  0
4861*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  3,  3,  0
4862	if (IS_PROBLEM_STATE(processor)) {
4863	  program_interrupt(processor, cia,
4864	                    privileged_instruction_program_interrupt);
4865	}
4866	else {
4867	  MSR = (MASKED(SRR1, 0, 32)
4868	         | MASKED(SRR1, 37, 41)
4869	         | MASKED(SRR1, 48, 63));
4870	  NIA = MASKED(SRR0, 0, 61);
4871	  cpu_synchronize_context(processor, cia);
4872	  check_masked_interrupts(processor);
4873	}
4874
4875#
4876# III.3.4.1 Move to/from System Register Instructions
4877#
4878
4879#0.31,6.RS,11.SPR,21.467,31./:XFX:::Move To Special Purpose Register
4880#0.31,6.RT,11.SPR,21.339,31./:XFX:::Move From Special Purpose Register
48810.31,6.RS,11./,16./,21.146,31./:X:::Move To Machine State Register
4882*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4883*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   2,  2,  0
4884*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   2,  2,  0
4885*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  1,  1,  0
4886	if (IS_PROBLEM_STATE(processor))
4887	  program_interrupt(processor, cia,
4888	                    privileged_instruction_program_interrupt);
4889	else {
4890	  MSR = *rS;
4891	  check_masked_interrupts(processor);
4892	}
4893
48940.31,6.RT,11./,16./,21.83,31./:X:::Move From Machine State Register
4895*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4896*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
4897*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
4898*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  3,  3,  0
4899	if (IS_PROBLEM_STATE(processor))
4900	  program_interrupt(processor, cia,
4901	                    privileged_instruction_program_interrupt);
4902	else {
4903	  *rT = MSR;
4904	  check_masked_interrupts(processor);
4905	}
4906
4907
4908#
4909# III.4.11.1 Cache Management Instructions
4910#
4911
49120.31,6./,11.RA,16.RB,21.470,31./:X::dcbi:Data Cache Block Invalidate
4913*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4914*603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   2,  2,  0
4915*603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   2,  2,  0
4916*604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
4917	if (IS_PROBLEM_STATE(processor))
4918	  program_interrupt(processor, cia,
4919	                    privileged_instruction_program_interrupt);
4920	else
4921	  TRACE(trace_tbd,("Data Cache Block Invalidate\n"));
4922
4923#
4924# III.4.11.2 Segment Register Manipulation Instructions
4925#
4926
49270.31,6.RS,11./,12.SR,16./,21.210,31./:X:32:mtsr %SR,%RS:Move To Segment Register
4928*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4929*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   2,  2,  0
4930*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   2,  2,  0
4931*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  1,  1,  0
4932	if (IS_PROBLEM_STATE(processor))
4933	  program_interrupt(processor, cia,
4934	                    privileged_instruction_program_interrupt);
4935	else
4936	  SEGREG(SR) = *rS;
4937
49380.31,6.RS,11./,16.RB,21.242,31./:X:32:mtsrin %RS,%RB:Move To Segment Register Indirect
4939*601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4940*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   2,  2,  0
4941*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   2,  2,  0
4942*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  1,  1,  0
4943	if (IS_PROBLEM_STATE(processor))
4944	  program_interrupt(processor, cia,
4945	                    privileged_instruction_program_interrupt);
4946	else
4947	  SEGREG(EXTRACTED32(*rB, 0, 3)) = *rS;
4948
49490.31,6.RT,11./,12.SR,16./,21.595,31./:X:32:mfsr %RT,%RS:Move From Segment Register
4950*601: PPC_UNIT_IU,    PPC_UNIT_IU,    2,  2,  0
4951*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   3,  3,  0
4952*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   3,  3,  0
4953*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  1,  1,  0
4954	if (IS_PROBLEM_STATE(processor))
4955	  program_interrupt(processor, cia,
4956	                    privileged_instruction_program_interrupt);
4957	else
4958	  *rT = SEGREG(SR);
4959
49600.31,6.RT,11./,16.RB,21.659,31./:X:32:mfsrin %RT,%RB:Move From Segment Register Indirect
4961*601: PPC_UNIT_IU,    PPC_UNIT_IU,    2,  2,  0
4962*603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   3,  3,  0
4963*603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   3,  3,  0
4964*604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  1,  1,  0
4965	if (IS_PROBLEM_STATE(processor))
4966	  program_interrupt(processor, cia,
4967	                    privileged_instruction_program_interrupt);
4968	else
4969	  *rT = SEGREG(EXTRACTED32(*rB, 0, 3));
4970
4971
4972#
4973# III.4.11.3 Lookaside Buffer Management Instructions (Optional)
4974#
4975
49760.31,6./,11./,16.RB,21.434,31./:X:64::SLB Invalidate Entry
4977
49780.31,6./,11./,16./,21.498,31./:X:64::SLB Invalidate All
4979
49800.31,6./,11./,16.RB,21.306,31./:X:::TLB Invalidate Entry
4981	if (IS_PROBLEM_STATE(processor))
4982	  program_interrupt(processor, cia,
4983	                    privileged_instruction_program_interrupt);
4984	else {
4985	  int nr = 0;
4986	  cpu *proc;
4987	  while (1) {
4988	    proc = psim_cpu(cpu_system(processor), nr);
4989	    if (proc == NULL) break;
4990	    cpu_page_tlb_invalidate_entry(proc, *rB);
4991	    nr++;
4992	  }
4993	}
4994
49950.31,6./,11./,16./,21.370,31./:X:::TLB Invalidate All
4996	if (IS_PROBLEM_STATE(processor))
4997	  program_interrupt(processor, cia,
4998	                    privileged_instruction_program_interrupt);
4999	else {
5000	  int nr = 0;
5001	  cpu *proc;
5002	  while (1) {
5003	    proc = psim_cpu(cpu_system(processor), nr);
5004	    if (proc == NULL) break;
5005	    cpu_page_tlb_invalidate_all(proc);
5006	    nr++;
5007	  }
5008	}
5009
50100.31,6./,11./,16./,21.566,31./:X:::TLB Synchronize
5011	/* nothing happens here - always in sync */
5012
5013#
5014# III.A.1.2 External Access Instructions
5015#
5016
50170.31,6.RT,11.RA,16.RB,21.310,31./:X:earwax::External Control In Word Indexed
5018
50190.31,6.RS,11.RA,16.RB,21.438,31./:X:earwax::External Control Out Word Indexed
5020
5021:include:::altivec.igen
5022:include:::e500.igen
5023