More scheduling stuff
[external/binutils.git] / sim / ppc / ppc-instructions
1 #
2 #   This file is part of the program psim.
3 #
4 #   Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
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 2 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, write to the Free Software
34 #   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
35 #
36 #   --
37 #
38 #
39 # Fields:
40 #
41 #       1       Instruction format as a `start-bit,content' pairs.
42 #               the content is one of a digit, field name or `/' (aka.0)
43 #
44 #       2       Format specifier
45 #
46 #       3       Flags:  64 - 64bit only
47 #                       f - floating point enabled required
48 #
49 #       4       short name
50 #
51 #       5       Description
52 #
53 #
54 # For flags marked 'model', the fields are interpreted as follows:
55 #
56 #       1       Not used
57 #
58 #       2       Not used
59 #
60 #       3       "macro"
61 #
62 #       4       String name for model
63 #
64 #       5       Specific CPU model, must be an identifier
65 #
66 #       6       Comma separated list of functional units
67
68 # PowerPC models
69 ::model:604:ppc604:  PPC_UNIT_BAD,   PPC_UNIT_BAD,   1,  1,  0
70 ::model:603e:ppc603e:PPC_UNIT_BAD,   PPC_UNIT_BAD,   1,  1,  0
71 ::model:603:ppc603:  PPC_UNIT_BAD,   PPC_UNIT_BAD,   1,  1,  0
72 ::model:601:ppc601:  PPC_UNIT_BAD,   PPC_UNIT_BAD,   1,  1,  0
73
74 # Flags for model.h
75 ::model-data:::
76         typedef enum _ppc_function_unit {
77           PPC_UNIT_BAD,                         /* unknown function unit */
78           PPC_UNIT_IU,                          /* integer unit (601/603 style) */
79           PPC_UNIT_SRU,                         /* system register unit (601/603 style) */
80           PPC_UNIT_SCIU1,                       /* 1st single cycle integer unit (604 style) */
81           PPC_UNIT_SCIU2,                       /* 2nd single cycle integer unit (604 style) */
82           PPC_UNIT_MCIU,                        /* multiple cycle integer unit (604 style) */
83           PPC_UNIT_FPU,                         /* floating point unit */
84           PPC_UNIT_LSU,                         /* load/store unit */
85           PPC_UNIT_BPU,                         /* branch unit */
86           nr_ppc_function_units
87         } ppc_function_unit;
88
89         /* Structure to hold timing information on a per instruction basis */
90         struct _model_time {
91           ppc_function_unit first_unit;                 /* first functional unit this insn could use */
92           ppc_function_unit last_unit;                  /* last functional unit this insn could use */
93           signed16          issue;                      /* # cycles before function unit can process other insns */
94           signed16          done;                       /* # cycles before insn is done */
95           unsigned32        flags;                      /* any flags that are needed */
96         };
97
98         /* Register mappings */
99         #define PPC_INT_REG     0                       /* start of integer registers */
100         #define PPC_FLOAT_REG   (PPC_INT_REG + 32)      /* start of floating point registers */
101         #define PPC_CR_REG      (PPC_FLOAT_REG + 32)    /* start of CR0 .. CR7 */
102         #define PPC_SPR_REG     (PPC_CR_REG + 8)        /* start of special purpose registers */
103         #define PPC_FPSCR_REG   (PPC_SPR_REG + 1024)    /* start of fpscr register */
104         #define NR_PPC_REGS     (PPC_FPSCR_REG + 1)     /* # of registers to allocate */
105
106         /* Structure for each register to indicate whether it is free or not */
107         typedef struct _model_reg model_reg;
108         struct _model_reg {
109           model_reg *next;                              /* next register to be released */
110           int in_use;                                   /* non zero if register is used */
111         };
112
113         /* Structure for each functional unit that is busy */
114         typedef struct _model_busy model_busy;
115         struct _model_busy {
116           model_busy *next;                             /* next function unit */
117           model_reg *reg;                               /* list of registers to release */
118           ppc_function_unit unit;                       /* function unit name */
119           signed16 issue;                               /* # of cycles until unit can accept another insn */
120           signed16 done;                                /* # of cycles until insn is done */
121         };
122
123         /* Structure to hold the current state information for the simulated CPU model */
124         struct _model_data {
125           cpu *processor;                               /* point back to processor */
126           const char *name;                             /* model name */
127           const model_time *timing;                     /* timing information */
128           model_busy *busy_list;                        /* list of busy function units */
129           model_busy *free_list;                        /* list of model_busy structs not in use */
130           model_reg registers[NR_PPC_REGS];             /* register status */
131           unsigned32 busy_mask;                         /* bitmask of busy function units */
132           count_type nr_cycles;                         /* # cycles */
133           count_type nr_branches;                       /* # branches */
134           count_type nr_branches_fallthrough;           /* # conditional branches that fell through */
135           count_type nr_branch_predict_trues;           /* # branches predicted correctly */
136           count_type nr_branch_predict_falses;          /* # branches predicted incorrectly */
137           count_type nr_stalls_data;                    /* # of stalls for data */
138           count_type nr_stalls_unit;                    /* # of stalls waiting for a function unit */
139           count_type nr_stalls_serialize;               /* # of stalls waiting for things to quiet down */
140           count_type nr_insns_not_handled;              /* # of instructions not handled */
141           count_type nr_units[nr_ppc_function_units];   /* function unit counts */
142           int insn_handled;                             /* whether last insn was handled */
143         };
144
145         STATIC_MODEL const char *const ppc_function_unit_name[ (int)nr_ppc_function_units ] = {
146           "unknown functional unit instruction",
147           "integer functional unit instruction",
148           "system register functional unit instruction",
149           "1st single cycle integer functional unit instruction",
150           "2nd single cycle integer functional unit instruction",
151           "multiple cycle integer functional unit instruction",
152           "floating point functional unit instruction",
153           "load/store functional unit instruction",
154           "branch functional unit instruction",
155         };
156
157 # Code called after executing the semantics of the function
158 void::model-function::model_cleanup:itable_index index, model_data *model_ptr
159         if (model_ptr->insn_handled)
160           model_ptr->insn_handled = 0;
161         else {
162           model_ptr->nr_insns_not_handled++;
163           TRACE(trace_tbd,("model specific code for %s not done\n", itable[index].name));
164         }
165
166 # Advance state to next cycle, releasing any registers allocated
167 void::model-internal::model_new_cycle:model_data *model_ptr
168         model_busy *cur_busy  = model_ptr->busy_list;
169         model_busy *free_list = model_ptr->free_list;
170         model_busy *next_busy = (model_busy *)0;
171         unsigned32 busy_mask  = model_ptr->busy_mask;
172         model_busy *next;
173
174         model_ptr->nr_cycles++;
175         for ( ; cur_busy; cur_busy = next) {
176           next = cur_busy->next;
177           if (--cur_busy->done <= 0) {          /* function unit done, release registers */
178             model_reg *reg = cur_busy->reg;
179             TRACE(trace_model,("done, retiring %s\n", ppc_function_unit_name[cur_busy->unit]));
180             while (reg) {
181               TRACE(trace_model,("freeing up reg, address 0x%lx (%d)\n", (long)reg, reg - &model_ptr->registers[0]));
182               reg->in_use = 0;
183               reg = reg->next;
184             }
185             busy_mask &= ~(1 << cur_busy->unit);
186             cur_busy->next = free_list;
187             free_list = cur_busy;
188           }
189           else if (--cur_busy->issue <= 0) {    /* function unit pipelined, allow new use */
190             TRACE(trace_model,("pipeline, %s ready for next client\n", ppc_function_unit_name[cur_busy->unit]));
191             busy_mask &= ~(1 << cur_busy->unit);
192             cur_busy->next = next_busy;
193             next_busy = cur_busy;
194           }
195           else {
196             TRACE(trace_model,("%s still working, issue = %d, done = %d\n",
197                                ppc_function_unit_name[cur_busy->unit],
198                                cur_busy->issue,
199                                cur_busy->done));
200             cur_busy->next = next_busy;
201             next_busy = cur_busy;
202           }
203         }
204
205         model_ptr->busy_list = next_busy;
206         model_ptr->free_list = free_list;
207         model_ptr->busy_mask = busy_mask;
208
209 # Mark a function unit as busy, return the busy structure so regs can be added to be released
210 model_busy *::model-internal::model_make_busy:model_data *model_ptr, ppc_function_unit unit, int issue, int done
211         model_busy *busy;
212
213         TRACE(trace_model,("unit = %s, issue = %d, done = %d\n", ppc_function_unit_name[unit], issue, done));
214         model_ptr->insn_handled = 1;
215
216         if (!model_ptr->free_list) {
217           busy = ZALLOC(model_busy);
218         }
219         else {
220           busy = model_ptr->free_list;
221           model_ptr->free_list = busy->next;
222           busy->reg = (model_reg *)0;
223         }
224         busy->next = model_ptr->busy_list;
225         busy->unit = unit;
226         busy->issue = issue;
227         busy->done = done;
228         model_ptr->busy_list = busy;
229         model_ptr->busy_mask |= (1 << unit);
230         model_ptr->nr_units[unit]++;
231         return busy;
232
233 # Wait until a function unit is non-busy, and then allocate a busy pointer & return the pointer
234 model_busy *::model-internal::model_wait_for_unit:itable_index index, model_data *const model_ptr, const model_time *const time_ptr
235         ppc_function_unit first_unit = time_ptr->first_unit;
236         ppc_function_unit last_unit = time_ptr->last_unit;
237         ppc_function_unit unit;
238         int stall_increment = 0;
239
240         for (;;) {
241           unsigned32 busy_mask = model_ptr->busy_mask;
242           for (unit = first_unit; unit <= last_unit; unit++) {
243             if (((1 << unit) & busy_mask) == 0) {
244               return model_make_busy(model_ptr, unit,
245                                      model_ptr->timing[index].issue,
246                                      model_ptr->timing[index].done);
247
248             }
249           }
250           TRACE(trace_model,("all function units are busy for %s\n", itable[index].name));
251           model_ptr->nr_stalls_unit += stall_increment;         /* don't count first stall */
252           stall_increment = 1;
253           model_new_cycle(model_ptr);
254         }
255
256 # Serialize the processor, waiting for all instructions to drain out before adding an instruction.
257 void::model-function::model_serialize:itable_index index, model_data *model_ptr
258         while (model_ptr->busy_list) {
259           TRACE(trace_model,("waiting for pipeline to empty\n"));
260           model_ptr->nr_stalls_serialize++;
261           model_new_cycle(model_ptr);
262         }
263         (void) model_make_busy(model_ptr,
264                                model_ptr->timing[index].first_unit,
265                                model_ptr->timing[index].issue,
266                                model_ptr->timing[index].done);
267
268 # Wait for a CR to become unbusy
269 void::model-function::model_wait_for_cr:model_data *model_ptr, unsigned CRBIT
270         unsigned u;
271         int cr_var = 0;
272         for (u = 0xc0000000; (u != 0) && (CRBIT & u) == 0; u >>= 4 )
273           cr_var++;
274
275         while (model_ptr->registers[cr_var + PPC_CR_REG].in_use) {
276           TRACE(trace_model,("waiting for CR %d\n", cr_var));
277           model_ptr->nr_stalls_data++;
278           model_new_cycle(model_ptr);
279         }
280
281 # Schedule an instruction that takes 2 integer input registers and produces an output register & possibly sets CR0
282 void::model-function::ppc_insn_int2:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rD, signed_word *rA, signed_word *rB, unsigned Rc
283         if (!WITH_MODEL_ISSUE)
284           return;
285
286         else {
287           registers *cpu_regs = cpu_registers(processor);
288           const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
289           const unsigned ppc_RB = (rB - &cpu_regs->gpr[0]) + PPC_INT_REG;
290           const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
291           model_reg *ppc_regs = model_ptr->registers;
292           model_busy *busy_ptr;
293
294           if (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
295             model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
296
297             while (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
298               model_ptr->nr_stalls_data++;
299               model_new_cycle(model_ptr);
300             }
301           }
302
303           busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
304            ppc_regs[ppc_RD].next = (model_reg *)0;
305            ppc_regs[ppc_RD].in_use = 1;
306            if (!Rc)
307              busy_ptr->reg = &ppc_regs[ppc_RD];
308            else {
309              model_reg *reg_CR0 = &ppc_regs[0 + PPC_CR_REG];
310              reg_CR0->next = &ppc_regs[ppc_RD];
311              busy_ptr->reg = reg_CR0;
312           }
313         }
314
315 # Schedule an instruction that takes 1 integer input registers and produces an output register & possibly sets CR0
316 void::model-function::ppc_insn_int1:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rD, signed_word *rA, unsigned Rc
317         if (!WITH_MODEL_ISSUE)
318           return;
319
320         else {
321           registers *cpu_regs = cpu_registers(processor);
322           const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
323           const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
324           model_reg *ppc_regs = model_ptr->registers;
325           model_busy *busy_ptr;
326
327         if (ppc_regs[ppc_RA].in_use) {
328             model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
329
330             while (ppc_regs[ppc_RA].in_use) {
331               model_ptr->nr_stalls_data++;
332               model_new_cycle(model_ptr);
333             }
334           }
335
336           busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
337           ppc_regs[ppc_RD].next = (model_reg *)0;
338           ppc_regs[ppc_RD].in_use = 1;
339           if (!Rc)
340             busy_ptr->reg = &ppc_regs[ppc_RD];
341           else {
342             model_reg *reg_CR0 = &ppc_regs[0 + PPC_CR_REG];
343             reg_CR0->next = &ppc_regs[ppc_RD];
344             busy_ptr->reg = reg_CR0;
345           }
346         }
347
348 # Schedule an instruction that takes no integer input registers and produces an output register & possibly sets CR0
349 void::model-function::ppc_insn_int0:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rD, unsigned Rc
350         if (!WITH_MODEL_ISSUE)
351           return;
352
353         else {
354           registers *cpu_regs = cpu_registers(processor);
355           const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
356           model_reg *ppc_regs = model_ptr->registers;
357           model_busy *busy_ptr;
358
359           busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
360           ppc_regs[ppc_RD].next = (model_reg *)0;
361           ppc_regs[ppc_RD].in_use = 1;
362           if (!Rc)
363             busy_ptr->reg = &ppc_regs[ppc_RD];
364           else {
365             model_reg *reg_CR0 = &ppc_regs[0 + PPC_CR_REG];
366             reg_CR0->next = &ppc_regs[ppc_RD];
367             busy_ptr->reg = reg_CR0;
368           }
369         }
370
371 # Schedule an instruction that takes 2 integer input registers and produces an output register & updates a second register
372 void::model-function::ppc_insn_int2_update:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rD, signed_word *rA, signed_word *rB
373         if (!WITH_MODEL_ISSUE)
374           return;
375
376         else {
377           registers *cpu_regs = cpu_registers(processor);
378           const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
379           const unsigned ppc_RB = (rB - &cpu_regs->gpr[0]) + PPC_INT_REG;
380           const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
381           model_reg *ppc_regs = model_ptr->registers;
382           model_busy *busy_ptr;
383
384           if (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
385             model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
386
387             while (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
388               model_ptr->nr_stalls_data++;
389               model_new_cycle(model_ptr);
390             }
391           }
392
393           busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
394           ppc_regs[ppc_RA].next = (model_reg *)0;
395           ppc_regs[ppc_RA].in_use = 1;
396
397           ppc_regs[ppc_RD].next = &ppc_regs[ppc_RA];
398           ppc_regs[ppc_RD].in_use = 1;
399           busy_ptr->reg = &ppc_regs[ppc_RD];
400         }
401
402 # Schedule an instruction that takes 1 integer input registers and produces an output register & updates the other register
403 void::model-function::ppc_insn_int1_update:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rD, signed_word *rA
404         if (!WITH_MODEL_ISSUE)
405           return;
406
407         else {
408           registers *cpu_regs = cpu_registers(processor);
409           const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
410           const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
411           model_reg *ppc_regs = model_ptr->registers;
412           model_busy *busy_ptr;
413
414           if (ppc_regs[ppc_RA].in_use) {
415             model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
416
417             while (ppc_regs[ppc_RA].in_use) {
418               model_ptr->nr_stalls_data++;
419               model_new_cycle(model_ptr);
420             }
421           }
422
423           busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
424           ppc_regs[ppc_RA].next = (model_reg *)0;
425           ppc_regs[ppc_RA].in_use = 1;
426
427           ppc_regs[ppc_RD].next = &ppc_regs[ppc_RA];
428           ppc_regs[ppc_RD].in_use = 1;
429           busy_ptr->reg = &ppc_regs[ppc_RD];
430         }
431
432 # Schedule an instruction that takes 2 integer input registers and produces no output register
433 void::model-function::ppc_insn_int2_noout:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rA, signed_word *rB
434         if (!WITH_MODEL_ISSUE)
435           return;
436
437         else {
438           registers *cpu_regs = cpu_registers(processor);
439           const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
440           const unsigned ppc_RB = (rB - &cpu_regs->gpr[0]) + PPC_INT_REG;
441           model_reg *ppc_regs = model_ptr->registers;
442
443           if (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
444             model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
445
446             while (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
447               model_ptr->nr_stalls_data++;
448               model_new_cycle(model_ptr);
449             }
450           }
451
452           (void) model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
453         }
454
455 # Schedule an instruction that takes 1 integer input registers and produces no output register
456 void::model-function::ppc_insn_int1_noout:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rA
457         if (!WITH_MODEL_ISSUE)
458           return;
459
460         else {
461           registers *cpu_regs = cpu_registers(processor);
462           const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
463           model_reg *ppc_regs = model_ptr->registers;
464
465           if (ppc_regs[ppc_RA].in_use) {
466             model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
467
468             while (ppc_regs[ppc_RA].in_use) {
469               model_ptr->nr_stalls_data++;
470               model_new_cycle(model_ptr);
471             }
472           }
473
474           (void) model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
475         }
476
477 # Schedule an instruction that takes no input registers and produces no output
478 void::model-function::ppc_insn_int0_noout:itable_index index, cpu *processor, model_data *model_ptr
479         if (!WITH_MODEL_ISSUE)
480           return;
481
482         else {
483           (void) model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
484         }
485
486 # Schedule an instruction that takes 2 integer input registers and produces a CR output register
487 void::model-function::ppc_insn_int2_cr:itable_index index, cpu *processor, model_data *model_ptr, unsigned CRD, signed_word *rA, signed_word *rB
488         if (!WITH_MODEL_ISSUE)
489           return;
490
491         else {
492           registers *cpu_regs = cpu_registers(processor);
493           const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
494           const unsigned ppc_RB = (rB - &cpu_regs->gpr[0]) + PPC_INT_REG;
495           const unsigned ppc_CRD = CRD + PPC_CR_REG;
496           model_reg *ppc_regs = model_ptr->registers;
497           model_busy *busy_ptr;
498
499           if (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
500             model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
501
502             while (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
503               model_ptr->nr_stalls_data++;
504               model_new_cycle(model_ptr);
505             }
506           }
507
508           busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
509           ppc_regs[ppc_CRD].next = (model_reg *)0;
510           ppc_regs[ppc_CRD].in_use = 1;
511           busy_ptr->reg = &ppc_regs[ppc_CRD];
512         }
513
514 # Schedule an instruction that takes 1 integer input register and produces a CR output register
515 void::model-function::ppc_insn_int1_cr:itable_index index, cpu *processor, model_data *model_ptr, unsigned CRD, signed_word *rA
516         if (!WITH_MODEL_ISSUE)
517           return;
518
519         else {
520           registers *cpu_regs = cpu_registers(processor);
521           const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
522           const unsigned ppc_CRD = CRD + PPC_CR_REG;
523           model_reg *ppc_regs = model_ptr->registers;
524           model_busy *busy_ptr;
525
526           if (ppc_regs[ppc_RA].in_use) {
527             model_new_cycle(model_ptr);                 /* don't count first dependency as a stall */
528
529             while (ppc_regs[ppc_RA].in_use) {
530               model_ptr->nr_stalls_data++;
531               model_new_cycle(model_ptr);
532             }
533           }
534
535           busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
536           ppc_regs[ppc_CRD].next = (model_reg *)0;
537           ppc_regs[ppc_CRD].in_use = 1;
538           busy_ptr->reg = &ppc_regs[ppc_CRD];
539         }
540
541 # Schedule an MFSPR instruction that takes 1 special purpose register and produces an integer output register
542 void::model-function::ppc_insn_from_spr:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rD, unsigned nSPR
543         if (!WITH_MODEL_ISSUE)
544           return;
545
546         else {
547           registers *cpu_regs = cpu_registers(processor);
548           const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
549           const unsigned ppc_SPR = nSPR + PPC_SPR_REG;
550           model_reg *ppc_regs = model_ptr->registers;
551           model_busy *busy_ptr;
552
553           while (ppc_regs[ppc_SPR].in_use) {
554             model_ptr->nr_stalls_data++;
555             model_new_cycle(model_ptr);
556           }
557
558           busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
559           ppc_regs[ppc_RD].next = (model_reg *)0;
560           ppc_regs[ppc_RD].in_use = 1;
561           busy_ptr->reg = &ppc_regs[ppc_RD];
562         }
563
564 # Schedule an MTSPR instruction that takes 1 integer register and produces a special purpose output register
565 void::model-function::ppc_insn_to_spr:itable_index index, cpu *processor, model_data *model_ptr, unsigned nSPR, signed_word *rS
566         if (!WITH_MODEL_ISSUE)
567           return;
568
569         else {
570           registers *cpu_regs = cpu_registers(processor);
571           const unsigned ppc_RS = (rS - &cpu_regs->gpr[0]) + PPC_INT_REG;
572           const unsigned ppc_SPR = nSPR + PPC_SPR_REG;
573           model_reg *ppc_regs = model_ptr->registers;
574           model_busy *busy_ptr;
575
576           while (ppc_regs[ppc_RS].in_use) {
577             model_ptr->nr_stalls_data++;
578             model_new_cycle(model_ptr);
579           }
580
581           busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
582           ppc_regs[ppc_SPR].next = (model_reg *)0;
583           ppc_regs[ppc_SPR].in_use = 1;
584           busy_ptr->reg = &ppc_regs[ppc_SPR];
585         }
586
587 model_data *::model-function::model_create:cpu *processor
588         model_data *model_ptr = ZALLOC(model_data);
589         ASSERT(CURRENT_MODEL > 0 && CURRENT_MODEL < nr_models);
590         model_ptr->name = model_name[CURRENT_MODEL];
591         model_ptr->timing = model_time_mapping[CURRENT_MODEL];
592         model_ptr->processor = processor;
593         model_ptr->nr_cycles = 1;
594         return model_ptr;
595
596 void::model-function::model_init:model_data *model_ptr
597
598 void::model-function::model_halt:model_data *model_ptr
599         /* Let pipeline drain */
600         while (model_ptr->busy_list)
601           model_new_cycle(model_ptr);
602
603 model_print *::model-function::model_mon_info:model_data *model_ptr
604         model_print *head;
605         model_print *tail;
606         ppc_function_unit i;
607
608         head = tail = ZALLOC(model_print);
609         tail->count = model_ptr->nr_cycles;
610         tail->name = "cycle";
611         tail->suffix_plural = "s";
612         tail->suffix_singular = "";
613
614         if (model_ptr->nr_stalls_data) {
615           tail->next = ZALLOC(model_print);
616           tail = tail->next;
617           tail->count = model_ptr->nr_stalls_data;
618           tail->name = "stall";
619           tail->suffix_plural = "s waiting for data";
620           tail->suffix_singular = " waiting for data";
621         }
622
623         if (model_ptr->nr_stalls_unit) {
624           tail->next = ZALLOC(model_print);
625           tail = tail->next;
626           tail->count = model_ptr->nr_stalls_unit;
627           tail->name = "stall";
628           tail->suffix_plural = "s waiting for a function unit";
629           tail->suffix_singular = " waiting for a function unit";
630         }
631
632         if (model_ptr->nr_stalls_serialize) {
633           tail->next = ZALLOC(model_print);
634           tail = tail->next;
635           tail->count = model_ptr->nr_stalls_serialize;
636           tail->name = "stall";
637           tail->suffix_plural = "s waiting for serialization";
638           tail->suffix_singular = " waiting for serialization";
639         }
640
641         if (model_ptr->nr_insns_not_handled) {
642           tail->next = ZALLOC(model_print);
643           tail = tail->next;
644           tail->count = model_ptr->nr_insns_not_handled;
645           tail->name = "instruction";
646           tail->suffix_plural = "s that were not accounted for in timing info";
647           tail->suffix_singular = " that was not accounted for in timing info";
648         }
649
650         if (model_ptr->nr_branches) {
651           tail->next = ZALLOC(model_print);
652           tail = tail->next;
653           tail->count = model_ptr->nr_branches;
654           tail->name = "branch";
655           tail->suffix_plural = "es";
656           tail->suffix_singular = "";
657         }
658
659         if (model_ptr->nr_branches_fallthrough) {
660           tail->next = ZALLOC(model_print);
661           tail = tail->next;
662           tail->count = model_ptr->nr_branches_fallthrough;
663           tail->name = "conditional branch";
664           tail->suffix_plural = "es fell through";
665           tail->suffix_singular = " fell through";
666         }
667
668         if (model_ptr->nr_branch_predict_trues) {
669           tail->next = ZALLOC(model_print);
670           tail = tail->next;
671           tail->count = model_ptr->nr_branch_predict_trues;
672           tail->name = "successful branch prediction";
673           tail->suffix_plural = "s";
674           tail->suffix_singular = "";
675         }
676
677         if (model_ptr->nr_branch_predict_falses) {
678           tail->next = ZALLOC(model_print);
679           tail = tail->next;
680           tail->count = model_ptr->nr_branch_predict_falses;
681           tail->name = "unsuccessful branch prediction";
682           tail->suffix_plural = "s";
683           tail->suffix_singular = "";
684         }
685
686         for (i = PPC_UNIT_BAD; i < nr_ppc_function_units; i++) {
687           if (model_ptr->nr_units[i]) {
688             tail->next = ZALLOC(model_print);
689             tail = tail->next;
690             tail->count = model_ptr->nr_units[i];
691             tail->name = ppc_function_unit_name[i];
692             tail->suffix_plural = "s";
693             tail->suffix_singular = "";
694           }
695         }
696
697         tail->next = (model_print *)0;
698         return head;
699
700 void::model-function::model_mon_info_free:model_data *model_ptr, model_print *ptr
701         while (ptr) {
702           model_print *next = ptr->next;
703           free((void *)ptr);
704           ptr = next;
705         }
706
707 void::model-function::model_branches:model_data *model_ptr, int failed
708         model_ptr->nr_units[PPC_UNIT_BPU]++;
709         model_ptr->insn_handled = 1;
710         if (failed)
711           model_ptr->nr_branches_fallthrough++;
712         else
713           model_ptr->nr_branches++;
714         model_new_cycle(model_ptr);     /* A branch always ends the current cycle */
715
716 void::model-function::model_branch_predict:model_data *model_ptr, int success
717         if (success)
718           model_ptr->nr_branch_predict_trues++;
719         else
720           model_ptr->nr_branch_predict_falses++;
721
722 # The following (illegal) instruction is `known' by gen and is
723 # called when ever an illegal instruction is encountered
724 ::internal::illegal
725         program_interrupt(processor, cia,
726                           illegal_instruction_program_interrupt);
727         return 0;
728
729
730 # The following (floating point unavailable) instruction is `known' by gen
731 # and is called when ever an a floating point instruction is to be
732 # executed but floating point is make unavailable by the MSR
733 ::internal::floating_point_unavailable
734         floating_point_unavailable_interrupt(processor, cia);
735         return 0;
736
737
738 #
739 # Floating point support functions
740 #
741
742 # Convert 32bit single to 64bit double
743 unsigned64::function::DOUBLE:unsigned32 WORD
744         unsigned64 FRT;
745         if (EXTRACTED32(WORD, 1, 8) > 0
746             && EXTRACTED32(WORD, 1, 8) < 255) {
747           /* normalized operand */
748           int not_word_1_1 = !EXTRACTED32(WORD, 1, 1); /*2.6.3 bug*/
749           FRT = (INSERTED64(EXTRACTED32(WORD, 0, 1), 0, 1)
750                  | INSERTED64(not_word_1_1, 2, 2)
751                  | INSERTED64(not_word_1_1, 3, 3)
752                  | INSERTED64(not_word_1_1, 4, 4)
753                  | INSERTED64(EXTRACTED32(WORD, 2, 31), 5, (63 - 29)));
754         }
755         else if (EXTRACTED32(WORD, 1, 8) == 0
756                  && EXTRACTED32(WORD, 9, 31) != 0) {
757           /* denormalized operand */
758           int sign = EXTRACTED32(WORD, 0, 0);
759           int exp = -126;
760           unsigned64 frac = INSERTED64(EXTRACTED32(WORD, 9, 31), 1, (52 - 29));
761           /* normalize the operand */
762           while (MASKED64(frac, 0, 0) == 0) {
763             frac <<= 1;
764             exp -= 1;
765           }
766           FRT = (INSERTED64(sign, 0, 0)
767                  | INSERTED64(exp + 1023, 1, 11)
768                  | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
769         }
770         else if (EXTRACTED32(WORD, 1, 8) == 255
771                  || EXTRACTED32(WORD, 1, 31) == 0) {
772           FRT = (INSERTED64(EXTRACTED32(WORD, 0, 1), 0, 1)
773                  | INSERTED64(EXTRACTED32(WORD, 1, 1), 2, 2)
774                  | INSERTED64(EXTRACTED32(WORD, 1, 1), 3, 3)
775                  | INSERTED64(EXTRACTED32(WORD, 1, 1), 4, 4)
776                  | INSERTED64(EXTRACTED32(WORD, 2, 31), 5, (63 - 29)));
777         }
778         else {
779           error("DOUBLE - unknown case\n");
780           FRT = 0;
781         }
782         return FRT;
783
784 # Convert 64bit single to 32bit double
785 unsigned32::function::SINGLE:unsigned64 FRS
786         unsigned32 WORD;
787         if (EXTRACTED64(FRS, 1, 11) > 896
788             || EXTRACTED64(FRS, 1, 63) == 0) {
789           /* no denormalization required (includes Zero/Infinity/NaN) */
790           WORD = (INSERTED32(EXTRACTED64(FRS, 0, 1), 0, 1)
791                   | INSERTED32(EXTRACTED64(FRS, 5, 34), 2, 31));
792         }
793         else if (874 <= EXTRACTED64(FRS, 1, 11)
794                  && EXTRACTED64(FRS, 1, 11) <= 896) {
795           /* denormalization required */
796           int sign = EXTRACTED64(FRS, 0, 0);
797           int exp = EXTRACTED64(FRS, 1, 11) - 1023;
798           unsigned64 frac = (BIT64(0)
799                              | INSERTED64(EXTRACTED64(FRS, 12, 63), 1, 52));
800           /* denormalize the operand */
801           while (exp < -126) {
802             frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63);
803             exp += 1;
804           }
805           WORD = (INSERTED32(sign, 0, 0)
806                   | INSERTED32(0x00, 1, 8)
807                   | INSERTED32(EXTRACTED64(frac, 1, 23), 9, 31));
808         }
809         else {
810           WORD = 0x0; /* ??? */
811         }         
812         return WORD;
813
814
815 # round 64bit double to 64bit but single
816 void::function::Round_Single:cpu *processor, int sign, int *exp, unsigned64 *frac_grx
817         /* comparisons ignore u bits */
818         unsigned64 out;
819         int inc = 0;
820         int lsb = EXTRACTED64(*frac_grx, 23, 23);
821         int gbit = EXTRACTED64(*frac_grx, 24, 24);
822         int rbit = EXTRACTED64(*frac_grx, 25, 25);
823         int xbit = EXTRACTED64(*frac_grx, 26, 55) != 0;
824         if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
825           if (lsb == 1 && gbit == 1) inc = 1;
826           if (lsb == 0 && gbit == 1 && rbit == 1) inc = 1;
827           if (lsb == 0 && gbit == 1 && xbit == 1) inc = 1;
828         }
829         if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_pos_infinity) {
830           if (sign == 0 && gbit == 1) inc = 1;
831           if (sign == 0 && rbit == 1) inc = 1;
832           if (sign == 0 && xbit == 1) inc = 1;
833         }
834         if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_neg_infinity) {
835           if (sign == 1 && gbit == 1) inc = 1;
836           if (sign == 1 && rbit == 1) inc = 1;
837           if (sign == 1 && xbit == 1) inc = 1;
838         }
839         /* work out addition in low 25 bits of out */
840         out = EXTRACTED64(*frac_grx, 0, 23) + inc;
841         *frac_grx = INSERTED64(out, 0, 23);
842         if (out & BIT64(64 - 23 - 1 - 1)) {
843           *frac_grx = (BIT64(0) |
844                        INSERTED64(EXTRACTED64(*frac_grx, 0, 22), 1, 23));
845           *exp = *exp + 1;
846         }
847         /* frac_grx[24:52] = 0 already */
848         FPSCR_SET_FR(inc);
849         FPSCR_SET_FI(gbit || rbit || xbit);
850
851
852 #
853 void::function::Round_Integer:cpu *processor, int sign, unsigned64 *frac, int *frac64, int gbit, int rbit, int xbit, fpscreg round_mode
854         int inc = 0;
855         if (round_mode == fpscr_rn_round_to_nearest) {
856           if (*frac64 == 1 && gbit == 1) inc = 1;
857           if (*frac64 == 0 && gbit == 1 && rbit == 1) inc = 1;
858           if (*frac64 == 0 && gbit == 1 && xbit == 1) inc = 1;
859         }
860         if (round_mode == fpscr_rn_round_towards_pos_infinity) {
861           if (sign == 0 && gbit == 1) inc = 1;
862           if (sign == 0 && rbit == 1) inc = 1;
863           if (sign == 0 && xbit == 1) inc = 1;
864         }
865         if (round_mode == fpscr_rn_round_towards_neg_infinity) {
866           if (sign == 1 && gbit == 1) inc = 1;
867           if (sign == 1 && rbit == 1) inc = 1;
868           if (sign == 1 && xbit == 1) inc = 1;
869         }
870         /* frac[0:64] = frac[0:64} + inc */
871         *frac += (*frac64 && inc ? 1 : 0);
872         *frac64 = (*frac64 + inc) & 0x1;
873         FPSCR_SET_FR(inc);
874         FPSCR_SET_FI(gbit | rbit | xbit);
875
876
877 void::function::Round_Float:cpu *processor, int sign, int *exp, unsigned64 *frac, fpscreg round_mode
878         int carry_out;
879         int inc = 0;
880         int lsb = EXTRACTED64(*frac, 52, 52);
881         int gbit = EXTRACTED64(*frac, 53, 53);
882         int rbit = EXTRACTED64(*frac, 54, 54);
883         int xbit = EXTRACTED64(*frac, 55, 55);
884         if (round_mode == fpscr_rn_round_to_nearest) {
885           if (lsb == 1 && gbit == 1) inc = 1;
886           if (lsb == 0 && gbit == 1 && rbit == 1) inc = 1;
887           if (lsb == 0 && gbit == 1 && xbit == 1) inc = 1;
888         }
889         if (round_mode == fpscr_rn_round_towards_pos_infinity) {
890           if (sign == 0 && gbit == 1) inc = 1;
891           if (sign == 0 && rbit == 1) inc = 1;
892           if (sign == 0 && xbit == 1) inc = 1;
893         }
894         if (round_mode == fpscr_rn_round_towards_neg_infinity) {
895           if (sign == 1 && gbit == 1) inc = 1;
896           if (sign == 1 && rbit == 1) inc = 1;
897           if (sign == 1 && xbit == 1) inc = 1;
898         }
899         /* frac//carry_out = frac + inc */
900         *frac = (*frac >> 1) + (INSERTED64(inc, 52, 52) >> 1);
901         carry_out = EXTRACTED64(*frac, 0, 0);
902         *frac <<= 1;
903         if (carry_out == 1) *exp = *exp + 1;
904         FPSCR_SET_FR(inc);
905         FPSCR_SET_FI(gbit | rbit | xbit);
906         FPSCR_SET_XX(FPSCR & fpscr_fi);
907
908
909 # conversion of FP to integer
910 void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64 *frt, unsigned64 frb, fpscreg round_mode, int tgt_precision
911         int i;
912         int exp = 0;
913         unsigned64 frac = 0;
914         int frac64 = 0;
915         int gbit = 0;
916         int rbit = 0;
917         int xbit = 0;
918         int sign = EXTRACTED64(frb, 0, 0);
919         if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 63) == 0)
920           goto Infinity_Operand;
921         if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 0)
922           goto SNaN_Operand;
923         if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 1)
924           goto QNaN_Operand;
925         if (EXTRACTED64(frb, 1, 11) > 1086) goto Large_Operand;
926         if (EXTRACTED64(frb, 1, 11) > 0) exp = EXTRACTED64(frb, 1, 11) - 1023;
927         if (EXTRACTED64(frb, 1, 11) == 0) exp = -1022;
928         if (EXTRACTED64(frb, 1, 11) > 0) { /* normal */
929           frac = BIT64(1) | INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
930           frac64 = 0;
931         }
932         if (EXTRACTED64(frb, 1, 11) == 0) { /* denorm */
933           frac = INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
934           frac64 = 0;
935         }
936         gbit = 0, rbit = 0, xbit = 0;
937         for (i = 1; i <= 63 - exp; i++) {
938           xbit = rbit | xbit;
939           rbit = gbit;
940           gbit = frac64;
941           frac64 = EXTRACTED64(frac, 63, 63);
942           frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63);
943         }
944         Round_Integer(processor, sign, &frac, &frac64, gbit, rbit, xbit, round_mode);
945         if (sign == 1) { /* frac[0:64] = ~frac[0:64] + 1 */
946           frac = ~frac;
947           frac64 ^= 1;
948           frac += (frac64 ? 1 : 0);
949           frac64 = (frac64 + 1) & 0x1;
950         }
951         if (tgt_precision == 32 /* can ignore frac64 in compare */
952             && (signed64)frac > (signed64)MASK64(33+1, 63)/*2^31-1 >>1*/)
953           goto Large_Operand;
954         if (tgt_precision == 64 /* can ignore frac64 in compare */
955             && (signed64)frac > (signed64)MASK64(1+1, 63)/*2^63-1 >>1*/)
956           goto Large_Operand;
957         if (tgt_precision == 32 /* can ignore frac64 in compare */
958             && (signed64)frac < (signed64)MASK64(0, 32+1)/*-2^31 >>1*/)
959           goto Large_Operand;
960         if (tgt_precision == 64 /* can ignore frac64 in compare */
961             && (signed64)frac < (signed64)MASK64(0, 0+1)/*-2^63 >>1*/)
962           goto Large_Operand;
963         FPSCR_SET_XX(FPSCR & fpscr_fi);
964         if (tgt_precision == 32)
965           *frt = MASKED64(*frt, 0, 31) | (EXTRACTED64(frac, 33, 63) << 1) | frac64;
966         if (tgt_precision == 64)
967           *frt = (EXTRACTED64(frac, 1, 63) << 1) | frac64;
968         /*FPSCR[fprf] = undefined */
969         goto Done;
970         /**/
971         Infinity_Operand:
972           FPSCR_SET_FR(0);
973           FPSCR_SET_FI(0);
974           FPSCR_OR_VX(fpscr_vxcvi);
975           if ((FPSCR & fpscr_ve) == 0) {
976             if (tgt_precision == 32) {
977               if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7FFFFFFF;
978               if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
979             }
980             else {
981               if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/
982               if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
983             }
984             /* FPSCR[FPRF] = undefined */
985           }
986           goto Done;
987         /**/
988         SNaN_Operand:
989           FPSCR_SET_FR(0);
990           FPSCR_SET_FI(0);
991           FPSCR_OR_VX(fpscr_vxsnan | fpscr_vxcvi);
992           if ((FPSCR & fpscr_ve) == 0) {
993             if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
994             if (tgt_precision == 64) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
995             /* FPSCR[fprf] = undefined */
996           }
997           goto Done;
998         /**/
999         QNaN_Operand:
1000           FPSCR_SET_FR(0);
1001           FPSCR_SET_FI(0);
1002           FPSCR_OR_VX(fpscr_vxcvi);
1003           if ((FPSCR & fpscr_ve) == 0) {
1004             if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1005             if (tgt_precision == 64) *frt = BIT64(0);/*0x8000_0000_0000_0000*/
1006             /* FPSCR[fprf] = undefined */
1007           }
1008           goto Done;
1009         /**/
1010         Large_Operand:
1011           FPSCR_SET_FR(0);
1012           FPSCR_SET_FI(0);
1013           FPSCR_OR_VX(fpscr_vxcvi);
1014           if ((FPSCR & fpscr_ve) == 0) {
1015             if (tgt_precision == 32) {
1016               if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7fffffff;
1017               if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1018             }
1019             else {
1020               if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/
1021               if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
1022             }
1023             /* FPSCR[fprf] = undefined */
1024           }
1025         /**/
1026         Done:
1027
1028
1029 # extract out raw fields of a FP number
1030 int::function::sign:unsigned64 FRS
1031         return (MASKED64(FRS, 0, 0)
1032                 ? -1
1033                 : 1);
1034 int::function::biased_exp:unsigned64 frs, int single
1035         if (single)
1036           return EXTRACTED64(frs, 1, 8);
1037         else
1038           return EXTRACTED64(frs, 1, 11);
1039 unsigned64::function::fraction:unsigned64 frs, int single
1040         if (single)
1041           return EXTRACTED64(frs, 9, 31);
1042         else
1043           return EXTRACTED64(frs, 12, 63);
1044
1045 # a number?, each of the below return +1 or -1 (based on sign bit)
1046 # if true.
1047 int::function::is_nor:unsigned64 frs, int single
1048         int exp = biased_exp(frs, single);
1049         return (exp >= 1
1050                 && exp <= (single ? 254 : 2046));
1051 int::function::is_zero:unsigned64 FRS
1052         return (MASKED64(FRS, 1, 63) == 0
1053                 ? sign(FRS)
1054                 : 0);
1055 int::function::is_den:unsigned64 frs, int single
1056         int exp = biased_exp(frs, single);
1057         unsigned64 frac = fraction(frs, single);
1058         return (exp == 0 && frac != 0
1059                 ? sign(frs)
1060                 : 0);
1061 int::function::is_inf:unsigned64 frs, int single
1062         int exp = biased_exp(frs, single);
1063         int frac = fraction(frs, single);
1064         return (exp == (single ? 255 : 2047) && frac == 0
1065                 ? sign(frs)
1066                 : 0);
1067 int::function::is_NaN:unsigned64 frs, int single
1068         int exp = biased_exp(frs, single);
1069         int frac = fraction(frs, single);
1070         return (exp == (single ? 255 : 2047) && frac != 0
1071                 ? sign(frs)
1072                 : 0);
1073 int::function::is_SNaN:unsigned64 frs, int single
1074         return (is_NaN(frs, single)
1075                 && !(frs & (single ? MASK64(9, 9) : MASK64(12, 12)))
1076                      ? sign(frs)
1077                      : 0);
1078 int::function::is_QNaN:unsigned64 frs, int single
1079         return (is_NaN(frs, single) && !is_SNaN(frs, single));
1080 int::function::is_less_than:unsigned64 *fra, unsigned64 *frb
1081         return *(double*)fra < *(double*)frb;
1082 int::function::is_greater_than:unsigned64 *fra, unsigned64 *frb
1083         return *(double*)fra > *(double*)frb;
1084 int::function::is_equan_to:unsigned64 *fra, unsigned64 *frb
1085         return *(double*)fra == *(double*)frb;
1086
1087
1088 # which quiet nan should become the result
1089 unsigned64::function::select_qnan:unsigned64 fra, unsigned64 frb, unsigned64 frc, int instruction_is_frsp, int generate_qnan, int single
1090         unsigned64 frt = 0;
1091         if (is_NaN(fra, single))
1092           frt = fra;
1093         else if (is_NaN(frb, single))
1094           if (instruction_is_frsp)
1095             frt = MASKED64(frb, 0, 34);
1096           else
1097             frt = frb;
1098         else if (is_NaN(frc, single))
1099           frt = frc;
1100         else if (generate_qnan)
1101           frt = MASK64(1, 12); /* 0x7FF8_0000_0000_0000 */
1102         else
1103           error("select_qnan - default reached\n");
1104         return frt;
1105
1106
1107 # detect invalid operation
1108 int::function::is_invalid_operation:cpu *processor, unsigned_word cia, unsigned64 fra, unsigned64 frb, fpscreg check, int single, int negate
1109         int fail = 0;
1110         if ((check & fpscr_vxsnan)
1111             && (is_SNaN(fra, single) || is_SNaN(frb, single))) {
1112           FPSCR_OR_VX(fpscr_vxsnan);
1113           fail = 1;
1114         }
1115         if ((check & fpscr_vxisi)
1116             && (is_inf(fra, single) && is_inf(frb, single))
1117             && ((negate && sign(fra) != sign(frb))
1118                 || (!negate && sign(fra) == sign(frb)))) {
1119            /*FIXME: don't handle inf-inf VS inf+-inf */
1120           FPSCR_OR_VX(fpscr_vxisi);
1121           fail = 1;
1122         }
1123         if ((check & fpscr_vxidi)
1124             && (is_inf(fra, single) && is_inf(frb, single))) {
1125           FPSCR_OR_VX(fpscr_vxidi);
1126           fail = 1;
1127         }
1128         if ((check & fpscr_vxzdz)
1129             && (is_zero(fra) && is_zero(frb))) {
1130           FPSCR_OR_VX(fpscr_vxzdz);
1131           fail = 1;
1132         }
1133         if ((check & fpscr_vximz)
1134             && (is_zero(fra) && is_inf(frb, single))) {
1135           FPSCR_OR_VX(fpscr_vximz);
1136           fail = 1;
1137         }
1138         if ((check & fpscr_vxvc)
1139             && (is_NaN(fra, single) || is_NaN(frb, single))) {
1140           FPSCR_OR_VX(fpscr_vxvc);
1141           fail = 1;
1142         }
1143         if ((check & fpscr_vxsoft)) {
1144           FPSCR_OR_VX(fpscr_vxsoft);
1145           fail = 1;
1146         }
1147         if ((check & fpscr_vxsqrt)
1148             && sign(fra) < 0) {
1149           FPSCR_OR_VX(fpscr_vxsqrt);
1150           fail = 1;
1151         }
1152         /* if ((check && fpscr_vxcvi) {
1153             && (is_inf(fra, single) || is_NaN(fra, single) || is_large(fra, single)))
1154           FPSCR_OR_VX(fpscr_vxcvi);
1155           fail = 1;
1156         }
1157         */
1158         return fail;
1159
1160
1161
1162
1163
1164 # handle case of invalid operation
1165 void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia, unsigned64 *frt, unsigned64 fra, unsigned64 frb, unsigned64 frc, int instruction_is_frsp, int instruction_is_convert_to_64bit, int instruction_is_convert_to_32bit, int single
1166         if (FPSCR & fpscr_ve) {
1167           /* invalid operation exception enabled */
1168           /* FRT unchaged */
1169           FPSCR_SET_FR(0);
1170           FPSCR_SET_FI(0);
1171           /* fpscr_FPRF unchanged */
1172         }
1173         else {
1174           /* invalid operation exception disabled */
1175           if (instruction_is_convert_to_64bit) {
1176             error("oopsi");
1177           }
1178           else if (instruction_is_convert_to_32bit) {
1179             error("oopsi");
1180           }
1181           else { /* arrith, frsp */
1182             *frt = select_qnan(fra, frb, frc,
1183                                instruction_is_frsp, 0/*generate*/, single);
1184             FPSCR_SET_FR(0);
1185             FPSCR_SET_FI(0);
1186             FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
1187           }
1188         }
1189
1190
1191
1192
1193 #
1194 # I.2.4.1 Branch Instructions
1195 #
1196 0.18,6.LI,30.AA,31.LK:I:t::Branch
1197 *601: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1198 *603: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1199 *603e:PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1200 *604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1201         if (AA) NIA = IEA(EXTS(LI_0b00));
1202         else    NIA = IEA(CIA + EXTS(LI_0b00));
1203         if (LK) LR = (spreg)CIA+4;
1204         model_branches(cpu_model(processor), 1);
1205
1206 0.16,6.BO,11.BI,16.BD,30.AA,31.LK:B:t::Branch Conditional
1207 *601: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1208 *603: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1209 *603e:PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1210 *604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1211         int M, ctr_ok, cond_ok, succeed;
1212         if (! BO{0})
1213           model_wait_for_cr(cpu_model(processor), BIT32_BI);
1214         if (is_64bit_implementation && is_64bit_mode) M = 0;
1215         else                                          M = 32;
1216         if (!BO{2}) CTR = CTR - 1;
1217         ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != (BO{3}));
1218         cond_ok = BO{0} || ((CR{BI}) == (BO{1}));
1219         if (ctr_ok && cond_ok) {
1220           if (AA) NIA = IEA(EXTS(BD_0b00));
1221           else    NIA = IEA(CIA + EXTS(BD_0b00));
1222           succeed = 1;
1223         }
1224         else
1225           succeed = 0;
1226         if (LK) LR = (spreg)IEA(CIA + 4);
1227         model_branches(cpu_model(processor), succeed);
1228         if (! BO{0}) {
1229           int reverse;
1230           if (BO{4}) {  /* branch prediction bit set, reverse sense of test */
1231             reverse = EXTS(BD_0b00) < 0;
1232           } else {      /* branch prediction bit not set */
1233             reverse = EXTS(BD_0b00) >= 0;
1234           }
1235           model_branch_predict(cpu_model(processor), reverse ? !succeed : succeed);
1236         }
1237
1238 0.19,6.BO,11.BI,16./,21.16,31.LK:XL:t::Branch Conditional to Link Register
1239 *601: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1240 *603: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1241 *603e:PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1242 *604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1243         int M, ctr_ok, cond_ok, succeed;
1244         if (is_64bit_implementation && is_64bit_mode) M = 0;
1245         else                                          M = 32;
1246         if (! BO{0})
1247           model_wait_for_cr(cpu_model(processor), BIT32_BI);
1248         if (!BO{2}) CTR = CTR - 1;
1249         ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != BO{3});
1250         cond_ok = BO{0} || (CR{BI} == BO{1});
1251         if (ctr_ok && cond_ok) {
1252           NIA = IEA(LR_0b00);
1253           succeed = 1;
1254         }
1255         else
1256           succeed = 0;
1257         if (LK) LR = (spreg)IEA(CIA + 4);
1258         model_branches(cpu_model(processor), succeed);
1259         if (! BO{0})
1260           model_branch_predict(cpu_model(processor), BO{4} ? !succeed : succeed);
1261
1262 0.19,6.BO,11.BI,16./,21.528,31.LK:XL:t::Branch Conditional to Count Register
1263 *601: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1264 *603: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1265 *603e:PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1266 *604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1267         int cond_ok, succeed;
1268         if (! BO{0})
1269           model_wait_for_cr(cpu_model(processor), BIT32_BI);
1270         cond_ok = BO{0} || (CR{BI} == BO{1});
1271         if (cond_ok) {
1272           NIA = IEA(CTR_0b00);
1273           succeed = 1;
1274         }
1275         else
1276           succeed = 0;
1277         if (LK) LR = (spreg)IEA(CIA + 4);
1278         model_branches(cpu_model(processor), succeed);
1279         if (! BO{0})
1280           model_branch_predict(cpu_model(processor), BO{4} ? !succeed : succeed);
1281
1282 #
1283 # I.2.4.2 System Call Instruction
1284 #
1285 0.17,6./,11./,16./,30.1,31./:SC:t::System Call
1286 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1287 *603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   3,  3,  0
1288 *603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   3,  3,  0
1289 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
1290         model_serialize(my_index, cpu_model(processor));
1291         system_call_interrupt(processor, cia);
1292
1293 #
1294 # I.2.4.3 Condition Register Logical Instructions
1295 #
1296 0.19,6.BT,11.BA,16.BB,21.257,31./:XL::crand:Condition Register AND
1297 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1298 *603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1299 *603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1300 *604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1301         BLIT32(CR, BT, CR{BA} && CR{BB});
1302
1303 0.19,6.BT,11.BA,16.BB,21.449,31./:XL::cror:Condition Register OR
1304 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1305 *603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1306 *603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1307 *604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1308         BLIT32(CR, BT, CR{BA} || CR{BB});
1309
1310 0.19,6.BT,11.BA,16.BB,21.193,31./:XL::crxor:Condition Register XOR
1311 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1312 *603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1313 *603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1314 *604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1315         BLIT32(CR, BT, CR{BA} != CR{BB});
1316
1317 0.19,6.BT,11.BA,16.BB,21.225,31./:XL::crnand:Condition Register NAND
1318 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1319 *603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1320 *603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1321 *604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1322         BLIT32(CR, BT, !(CR{BA} && CR{BB}));
1323
1324 0.19,6.BT,11.BA,16.BB,21.33,31./:XL::crnor:Condition Register NOR
1325 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1326 *603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1327 *603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1328 *604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1329         BLIT32(CR, BT, !(CR{BA} || CR{BB}));
1330
1331 0.19,6.BT,11.BA,16.BB,21.289,31./:XL::creqv:Condition Register Equivalent
1332 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1333 *603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1334 *603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1335 *604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1336         BLIT32(CR, BT, CR{BA} == CR{BB});
1337
1338 0.19,6.BT,11.BA,16.BB,21.129,31./:XL::crandc:Condition Register AND with Complement
1339 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1340 *603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1341 *603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1342 *604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1343         BLIT32(CR, BT, CR{BA} && !CR{BB});
1344
1345 0.19,6.BT,11.BA,16.BB,21.417,31./:XL::crorc:Condition Register OR with Complement
1346 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1347 *603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1348 *603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1349 *604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1350         BLIT32(CR, BT, CR{BA} || !CR{BB});
1351
1352 #
1353 # I.2.4.4 Condition Register Field Instruction
1354 #
1355 0.19,6.BF,9./,11.BFA,14./,16./,21.0,31./:XL:::Move Condition Register Field
1356 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1357 *603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1358 *603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
1359 *604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  1,  0
1360         MBLIT32(CR, 4*BF, 4*BF+3, EXTRACTED32(CR, 4*BFA, 4*BFA+3));
1361
1362
1363 #
1364 # I.3.3.2 Fixed-Point Load Instructions
1365 #
1366
1367 0.34,6.RT,11.RA,16.D:D:::Load Byte and Zero
1368 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1369 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1370 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1371 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1372         unsigned_word b;
1373         unsigned_word EA;
1374         if (RA == 0) b = 0;
1375         else         b = *rA;
1376         EA = b + EXTS(D);
1377         *rT = MEM(unsigned, EA, 1);
1378         if (RA == 0)
1379           ppc_insn_int0(my_index, processor, cpu_model(processor), rT, 0/*Rc*/);
1380         else
1381           ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
1382
1383
1384 0.31,6.RT,11.RA,16.RB,21.87,31./:X:::Load Byte and Zero Indexed
1385 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1386 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1387 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1388 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1389         unsigned_word b;
1390         unsigned_word EA;
1391         if (RA == 0) b = 0;
1392         else         b = *rA;
1393         EA = b + *rB;
1394         *rT = MEM(unsigned, EA, 1);
1395         if (RA == 0)
1396           ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rB, 0/*Rc*/);
1397         else
1398           ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, 0/*Rc*/);
1399
1400 0.35,6.RT,11.RA,16.D:D:::Load Byte and Zero with Update
1401 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1402 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1403 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1404 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1405         unsigned_word EA;
1406         if (RA == 0 || RA == RT)
1407           program_interrupt(processor, cia,
1408                             illegal_instruction_program_interrupt);
1409         EA = *rA + EXTS(D);
1410         *rT = MEM(unsigned, EA, 1);
1411         *rA = EA;
1412         ppc_insn_int1_update(my_index, processor, cpu_model(processor), rT, rA);
1413
1414 0.31,6.RT,11.RA,16.RB,21.119,31./:X:::Load Byte and Zero with Update Indexed
1415 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1416 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1417 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1418 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1419         unsigned_word EA;
1420         if (RA == 0 || RA == RT)
1421           program_interrupt(processor, cia,
1422                             illegal_instruction_program_interrupt);
1423         EA = *rA + *rB;
1424         *rT = MEM(unsigned, EA, 1);
1425         *rA = EA;
1426         ppc_insn_int2_update(my_index, processor, cpu_model(processor), rT, rA, rB);
1427
1428 0.40,6.RT,11.RA,16.D:D:::Load Halfword and Zero
1429 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1430 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1431 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1432 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1433         unsigned_word b;
1434         unsigned_word EA;
1435         if (RA == 0) b = 0;
1436         else         b = *rA;
1437         EA = b + EXTS(D);
1438         *rT = MEM(unsigned, EA, 2);
1439         if (RA == 0)
1440           ppc_insn_int0(my_index, processor, cpu_model(processor), rT, 0/*Rc*/);
1441         else
1442           ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
1443
1444 0.31,6.RT,11.RA,16.RB,21.279,31./:X:::Load Halfword and Zero Indexed
1445 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1446 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1447 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1448 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1449         unsigned_word b;
1450         unsigned_word EA;
1451         if (RA == 0) b = 0;
1452         else         b = *rA;
1453         EA = b + *rB;
1454         *rT = MEM(unsigned, EA, 2);
1455         if (RA == 0)
1456           ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rB, 0/*Rc*/);
1457         else
1458           ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, 0/*Rc*/);
1459
1460 0.41,6.RT,11.RA,16.D:D:::Load Halfword and Zero with Update
1461 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1462 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1463 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1464 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1465         unsigned_word EA;
1466         if (RA == 0 || RA == RT)
1467           program_interrupt(processor, cia,
1468                             illegal_instruction_program_interrupt);
1469         EA = *rA + EXTS(D);
1470         *rT = MEM(unsigned, EA, 2);
1471         *rA = EA;
1472         ppc_insn_int1_update(my_index, processor, cpu_model(processor), rT, rA);
1473
1474 0.31,6.RT,11.RA,16.RB,21.311,31./:X:::Load Halfword and Zero with Update Indexed
1475 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1476 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1477 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1478 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1479         unsigned_word EA;
1480         if (RA == 0 || RA == RT)
1481           program_interrupt(processor, cia,
1482                             illegal_instruction_program_interrupt);
1483         EA = *rA + *rB;
1484         *rT = MEM(unsigned, EA, 2);
1485         *rA = EA;
1486         ppc_insn_int2_update(my_index, processor, cpu_model(processor), rT, rA, rB);
1487
1488 0.42,6.RT,11.RA,16.D:D:::Load Halfword Algebraic
1489 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1490 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1491 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1492 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1493         unsigned_word b;
1494         unsigned_word EA;
1495         if (RA == 0) b = 0;
1496         else         b = *rA;
1497         EA = b + EXTS(D);
1498         *rT = MEM(signed, EA, 2);
1499         if (RA == 0)
1500           ppc_insn_int0(my_index, processor, cpu_model(processor), rT, 0/*Rc*/);
1501         else
1502           ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
1503
1504 0.31,6.RT,11.RA,16.RB,21.343,31./:X:::Load Halfword Algebraic Indexed
1505 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1506 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1507 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1508 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1509         unsigned_word b;
1510         unsigned_word EA;
1511         if (RA == 0) b = 0;
1512         else         b = *rA;
1513         EA = b + *rB;
1514         *rT = MEM(signed, EA, 2);
1515         if (RA == 0)
1516           ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rB, 0/*Rc*/);
1517         else
1518           ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, 0/*Rc*/);
1519
1520 0.43,6.RT,11.RA,16.D:D:::Load Halfword Algebraic with Update
1521 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1522 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1523 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1524 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1525         unsigned_word EA;
1526         if (RA == 0 || RA == RT)
1527           program_interrupt(processor, cia,
1528                             illegal_instruction_program_interrupt);
1529         EA = *rA + EXTS(D);
1530         *rT = MEM(signed, EA, 2);
1531         ppc_insn_int1_update(my_index, processor, cpu_model(processor), rT, rA);
1532
1533 0.31,6.RT,11.RA,16.RB,21.375,31./:X:::Load Halfword Algebraic with Update Indexed
1534 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1535 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1536 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1537 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1538         unsigned_word EA;
1539         if (RA == 0 || RA == RT)
1540           program_interrupt(processor, cia,
1541                             illegal_instruction_program_interrupt);
1542         EA = *rA + *rB;
1543         *rT = MEM(signed, EA, 2);
1544         *rA = EA;
1545         ppc_insn_int2_update(my_index, processor, cpu_model(processor), rT, rA, rB);
1546
1547 0.32,6.RT,11.RA,16.D:D:::Load Word and Zero
1548 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1549 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1550 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1551 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1552         unsigned_word b;
1553         unsigned_word EA;
1554         if (RA == 0) b = 0;
1555         else         b = *rA;
1556         EA = b + EXTS(D);
1557         *rT = MEM(unsigned, EA, 4);
1558         if (RA == 0)
1559           ppc_insn_int0(my_index, processor, cpu_model(processor), rT, 0/*Rc*/);
1560         else
1561           ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
1562
1563 0.31,6.RT,11.RA,16.RB,21.23,31./:X:::Load Word and Zero Indexed
1564 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1565 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1566 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1567 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1568         unsigned_word b;
1569         unsigned_word EA;
1570         if (RA == 0) b = 0;
1571         else         b = *rA;
1572         EA = b + *rB;
1573         *rT = MEM(unsigned, EA, 4);
1574         if (RA == 0)
1575           ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rB, 0/*Rc*/);
1576         else
1577           ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, 0/*Rc*/);
1578
1579 0.33,6.RT,11.RA,16.D:D:::Load Word and Zero with Update
1580 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1581 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1582 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1583 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1584         unsigned_word EA;
1585         if (RA == 0 || RA == RT)
1586           program_interrupt(processor, cia,
1587                             illegal_instruction_program_interrupt);
1588         EA = *rA + EXTS(D);
1589         *rT = MEM(unsigned, EA, 4);
1590         *rA = EA;
1591         ppc_insn_int1_update(my_index, processor, cpu_model(processor), rT, rA);
1592
1593 0.31,6.RT,11.RA,16.RB,21.55,31./:X:::Load Word and Zero with Update Indexed
1594 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  2,  0
1595 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1596 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1597 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1598         unsigned_word EA;
1599         if (RA == 0 || RA == RT)
1600           program_interrupt(processor, cia,
1601                             illegal_instruction_program_interrupt);
1602         EA = *rA + *rB;
1603         *rT = MEM(unsigned, EA, 4);
1604         *rA = EA;
1605         ppc_insn_int2_update(my_index, processor, cpu_model(processor), rT, rA, rB);
1606
1607 0.58,6.RT,11.RA,16.DS,30.2:DS:64::Load Word Algebraic
1608 #       unsigned_word b;
1609 #       unsigned_word EA;
1610 #       if (RA == 0) b = 0;
1611 #       else         b = *rA;
1612 #       EA = b + EXTS(DS_0b00);
1613 #       *rT = MEM(signed, EA, 4);
1614
1615 0.31,6.RT,11.RA,16.RB,21.341,31./:X:64::Load Word Algebraic Indexed
1616 #       unsigned_word b;
1617 #       unsigned_word EA;
1618 #       if (RA == 0) b = 0;
1619 #       else         b = *rA;
1620 #       EA = b + *rB;;
1621 #       *rT = MEM(signed, EA, 4);
1622
1623 0.31,6.RT,11.RA,16.RB,21.373,31./:X:64::Load Word Algebraic with Update Indexed
1624 #       unsigned_word EA;
1625 #       if (RA == 0 || RA == RT)
1626 #         program_interrupt(processor, cia
1627 #                           illegal_instruction_program_interrupt);
1628 #       EA = *rA + *rB;
1629 #       *rT = MEM(signed, EA, 4);
1630 #       *rA = EA;
1631
1632 0.58,6.RT,11.RA,16.DS,30.0:DS:64::Load Doubleword
1633 #       unsigned_word b;
1634 #       unsigned_word EA;
1635 #       if (RA == 0) b = 0;
1636 #       else         b = *rA;
1637 #       EA = b + EXTS(DS_0b00);
1638 #       *rT = MEM(unsigned, EA, 8);
1639
1640 0.31,6.RT,11.RA,16.RB,21.21,31./:X:64::Load Doubleword Indexed
1641 #       unsigned_word b;
1642 #       unsigned_word EA;
1643 #       if (RA == 0) b = 0;
1644 #       else         b = *rA;
1645 #       EA = b + *rB;
1646 #       *rT = MEM(unsigned, EA, 8);
1647
1648 0.58,6.RT,11.RA,16.DS,30.1:DS:64::Load Doubleword with Update
1649 #       unsigned_word EA;
1650 #       if (RA == 0 || RA == RT)
1651 #         program_interrupt(processor, cia
1652 #                           illegal_instruction_program_interrupt);
1653 #       EA = *rA + EXTS(DS_0b00);
1654 #       *rT = MEM(unsigned, EA, 8);
1655 #       *rA = EA;
1656
1657 0.31,6.RT,11.RA,16.RB,21.53,31./:DS:64::Load Doubleword with Update Indexed
1658 #       unsigned_word EA;
1659 #       if (RA == 0 || RA == RT)
1660 #         program_interrupt(processor, cia
1661 #                           illegal_instruction_program_interrupt);
1662 #       EA = *rA + *rB;
1663 #       *rT = MEM(unsigned, EA, 8);
1664 #       *rA = EA;
1665
1666
1667
1668 #
1669 # I.3.3.3 Fixed-Point Store Instructions
1670 #
1671
1672 0.38,6.RS,11.RA,16.D:D:::Store Byte
1673 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1674 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1675 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1676 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
1677         unsigned_word b;
1678         unsigned_word EA;
1679         if (RA == 0) b = 0;
1680         else         b = *rA;
1681         EA = b + EXTS(D);
1682         STORE(EA, 1, *rS);
1683         if (RA == 0)
1684           ppc_insn_int0_noout(my_index, processor, cpu_model(processor));
1685         else
1686           ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rA);
1687
1688 0.31,6.RS,11.RA,16.RB,21.215,31./:X:::Store Byte Indexed
1689 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1690 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1691 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1692 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
1693         unsigned_word b;
1694         unsigned_word EA;
1695         if (RA == 0) b = 0;
1696         else         b = *rA;
1697         EA = b + *rB;
1698         STORE(EA, 1, *rS);
1699         if (RA == 0)
1700           ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
1701         else
1702           ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
1703
1704 0.39,6.RS,11.RA,16.D:D:::Store Byte with Update
1705 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1706 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1707 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1708 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
1709         unsigned_word EA;
1710         if (RA == 0)
1711           program_interrupt(processor, cia,
1712                             illegal_instruction_program_interrupt);
1713         EA = *rA + EXTS(D);
1714         STORE(EA, 1, *rS);
1715         *rA = EA;
1716         ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rA, 0/*Rc*/);
1717
1718 0.31,6.RS,11.RA,16.RB,21.247,31./:X:::Store Byte with Update Indexed
1719 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  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,  3,  0
1723         unsigned_word EA;
1724         if (RA == 0)
1725           program_interrupt(processor, cia,
1726                             illegal_instruction_program_interrupt);
1727         EA = *rA + *rB;
1728         STORE(EA, 1, *rS);
1729         *rA = EA;
1730         ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rA, rB, 0/*Rc*/);
1731
1732 0.44,6.RS,11.RA,16.D:D:::Store Half Word
1733 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  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,  3,  0
1737         unsigned_word b;
1738         unsigned_word EA;
1739         if (RA == 0) b = 0;
1740         else         b = *rA;
1741         EA = b + EXTS(D);
1742         STORE(EA, 2, *rS);
1743         if (RA == 0)
1744           ppc_insn_int0_noout(my_index, processor, cpu_model(processor));
1745         else
1746           ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rA);
1747
1748 0.31,6.RS,11.RA,16.RB,21.407,31./:X:::Store Half Word Indexed
1749 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1750 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1751 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1752 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
1753         unsigned_word b;
1754         unsigned_word EA;
1755         if (RA == 0) b = 0;
1756         else         b = *rA;
1757         EA = b + *rB;
1758         STORE(EA, 2, *rS);
1759         if (RA == 0)
1760           ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
1761         else
1762           ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
1763
1764 0.45,6.RS,11.RA,16.D:D:::Store Half Word with Update
1765 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1766 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1767 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1768 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
1769         unsigned_word EA;
1770         if (RA == 0)
1771           program_interrupt(processor, cia,
1772                             illegal_instruction_program_interrupt);
1773         EA = *rA + EXTS(D);
1774         STORE(EA, 2, *rS);
1775         *rA = EA;
1776         ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rA, 0/*Rc*/);
1777
1778 0.31,6.RS,11.RA,16.RB,21.439,31./:X:::Store Half Word with Update Indexed
1779 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1780 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1781 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1782 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
1783         unsigned_word EA;
1784         if (RA == 0)
1785           program_interrupt(processor, cia,
1786                             illegal_instruction_program_interrupt);
1787         EA = *rA + *rB;
1788         STORE(EA, 2, *rS);
1789         *rA = EA;
1790         ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rA, rB, 0/*Rc*/);
1791
1792 0.36,6.RS,11.RA,16.D:D:::Store Word
1793 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1794 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1795 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1796 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
1797         unsigned_word b;
1798         unsigned_word EA;
1799         if (RA == 0) b = 0;
1800         else         b = *rA;
1801         EA = b + EXTS(D);
1802         STORE(EA, 4, *rS);
1803         if (RA == 0)
1804           ppc_insn_int0_noout(my_index, processor, cpu_model(processor));
1805         else
1806           ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rA);
1807
1808 0.31,6.RS,11.RA,16.RB,21.151,31./:X:::Store Word Indexed
1809 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1810 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1811 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1812 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
1813         unsigned_word b;
1814         unsigned_word EA;
1815         if (RA == 0) b = 0;
1816         else         b = *rA;
1817         EA = b + *rB;
1818         STORE(EA, 4, *rS);
1819         if (RA == 0)
1820           ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
1821         else
1822           ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
1823
1824 0.37,6.RS,11.RA,16.D:D:::Store Word with Update
1825 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1826 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1827 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1828 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
1829         unsigned_word EA;
1830         if (RA == 0)
1831           program_interrupt(processor, cia,
1832                             illegal_instruction_program_interrupt);
1833         EA = *rA + EXTS(D);
1834         STORE(EA, 4, *rS);
1835         *rA = EA;
1836         ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rA, 0/*Rc*/);
1837
1838 0.31,6.RS,11.RA,16.RB,21.183,31./:X:::Store Word with Update Indexed
1839 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1840 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1841 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1842 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
1843         unsigned_word EA;
1844         if (RA == 0)
1845           program_interrupt(processor, cia,
1846                             illegal_instruction_program_interrupt);
1847         EA = *rA + *rB;
1848         STORE(EA, 4, *rS);
1849         *rA = EA;
1850         ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rA, rB, 0/*Rc*/);
1851
1852 0.62,6.RS,11.RA,16.DS,30.0:DS:64::Store Doubleword
1853 #       unsigned_word b;
1854 #       unsigned_word EA;
1855 #       if (RA == 0) b = 0;
1856 #       else         b = *rA;
1857 #       EA = b + EXTS(DS_0b00);
1858 #       STORE(EA, 8, *rS);
1859 0.31,6.RS,11.RA,16.RB,21.149,31./:X:64::Store Doubleword Indexed
1860 #       unsigned_word b;
1861 #       unsigned_word EA;
1862 #       if (RA == 0) b = 0;
1863 #       else         b = *rA;
1864 #       EA = b + *rB;
1865 #       STORE(EA, 8, *rS);
1866 0.62,6.RS,11.RA,16.DS,30.1:DS:64::Store Doubleword with Update
1867 #       unsigned_word EA;
1868 #       if (RA == 0)
1869 #         program_interrupt(processor, cia
1870 #                           illegal_instruction_program_interrupt);
1871 #       EA = *rA + EXTS(DS_0b00);
1872 #       STORE(EA, 8, *rS);
1873 #       *rA = EA;
1874 0.31,6.RS,11.RA,16.RB,21.181,31./:X:64::Store Doubleword with Update Indexed
1875 #       unsigned_word EA;
1876 #       if (RA == 0)
1877 #         program_interrupt(processor, cia
1878 #                           illegal_instruction_program_interrupt);
1879 #       EA = *rA + *rB;
1880 #       STORE(EA, 8, *rS);
1881 #       *rA = EA;
1882
1883
1884 #
1885 # I.3.3.4 Fixed-Point Load and Store with Byte Reversal Instructions
1886 #
1887
1888 0.31,6.RT,11.RA,16.RB,21.790,31./:X:::Load Halfword Byte-Reverse Indexed
1889 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1890 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1891 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1892 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
1893         unsigned_word b;
1894         unsigned_word EA;
1895         if (RA == 0) b = 0;
1896         else         b = *rA;
1897         EA = b + *rB;
1898         *rT = SWAP_2(MEM(unsigned, EA, 2));
1899         if (RA == 0)
1900           ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rB, 0/*Rc*/);
1901         else
1902           ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, 0/*Rc*/);
1903
1904 0.31,6.RT,11.RA,16.RB,21.534,31./:X:::Load Word Byte-Reverse Indexed
1905 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1906 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1907 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1908 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
1909         unsigned_word b;
1910         unsigned_word EA;
1911         if (RA == 0) b = 0;
1912         else         b = *rA;
1913         EA = b + *rB;
1914         *rT = SWAP_4(MEM(unsigned, EA, 4));
1915         if (RA == 0)
1916           ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rB, 0/*Rc*/);
1917         else
1918           ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, 0/*Rc*/);
1919
1920 0.31,6.RS,11.RA,16.RB,21.918,31./:X:::Store Half Word Byte-Reversed Indexed
1921 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1922 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1923 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1924 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
1925         unsigned_word b;
1926         unsigned_word EA;
1927         if (RA == 0) b = 0;
1928         else         b = *rA;
1929         EA = b + *rB;
1930         STORE(EA, 2, SWAP_2(*rS));
1931         if (RA == 0)
1932           ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
1933         else
1934           ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
1935
1936 0.31,6.RS,11.RA,16.RB,21.662,31./:X:::Store Word Byte-Reversed Indexed
1937 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
1938 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1939 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
1940 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
1941         unsigned_word b;
1942         unsigned_word EA;
1943         if (RA == 0) b = 0;
1944         else         b = *rA;
1945         EA = b + *rB;
1946         STORE(EA, 4, SWAP_4(*rS));
1947         if (RA == 0)
1948           ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
1949         else
1950           ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
1951
1952
1953 #
1954 # I.3.3.5 Fixed-Point Load and Store Multiple Instrctions
1955 #
1956
1957 0.46,6.RT,11.RA,16.D:D:be::Load Multiple Word
1958
1959 0.47,6.RS,11.RA,16.D:D:be::Store Multiple Word
1960
1961
1962 #
1963 # I.3.3.6 Fixed-Point Move Assist Instructions
1964 #
1965
1966 0.31,6.RT,11.RA,16.NB,21.597,31./:X:be::Load String Word Immediate
1967
1968 0.31,6.RT,11.RA,16.RB,21.533,31./:X:be::Load String Word Indexed
1969
1970 0.31,6.RS,11.RA,16.NB,21.725,31./:X:be::Store String Word Immedate
1971
1972 0.31,6.RS,11.RA,16.RB,21.661,31./:X:be::Store String Word Indexed
1973
1974
1975 #
1976 # I.3.3.7 Storage Synchronization Instructions
1977 #
1978 # HACK: Rather than monitor addresses looking for a reason
1979 #       to cancel a reservation.  This code instead keeps
1980 #       a copy of the data read from memory.  Before performing
1981 #       a store, the memory area is checked to see if it has
1982 #       been changed.
1983 0.31,6.RT,11.RA,16.RB,21.20,31./:X:::Load Word And Reserve Indexed
1984 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    2,  2,  0
1985 *603: PPC_UNIT_LSU,   PPC_UNIT_IU,    1,  2,  0
1986 *603e:PPC_UNIT_LSU,   PPC_UNIT_IU,    1,  2,  0
1987 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
1988         unsigned_word b;
1989         unsigned_word EA;
1990         if (RA == 0) b = 0;
1991         else         b = *rA;
1992         EA = b + *rB;
1993         RESERVE = 1;
1994         RESERVE_ADDR = real_addr(EA, 1/*is-read?*/);
1995         RESERVE_DATA = MEM(unsigned, EA, 4);
1996         *rT = RESERVE_DATA;
1997
1998 0.31,6.RT,11.RA,16.RB,21.84,31./:X:64::Load Doubleword And Reserve Indexed
1999         unsigned_word b;
2000         unsigned_word EA;
2001         if (RA == 0) b = 0;
2002         else         b = *rA;
2003         EA = b + *rB;
2004         RESERVE = 1;
2005         RESERVE_ADDR = real_addr(EA, 1/*is-read?*/);
2006         RESERVE_DATA = MEM(unsigned, EA, 8);
2007         *rT = RESERVE_DATA;
2008
2009 0.31,6.RS,11.RA,16.RB,21.150,31.1:X:::Store Word Conditional Indexed
2010 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2011 *603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   8,  8,  0
2012 *603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   8,  8,  0
2013 *604: PPC_UNIT_BPU,   PPC_UNIT_BPU,   1,  3,  0
2014         unsigned_word b;
2015         unsigned_word EA;
2016         if (RA == 0) b = 0;
2017         else         b = *rA;
2018         EA = b + *rB;
2019         if (RESERVE) {
2020           if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/)
2021               && /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 4)) {
2022             STORE(EA, 4, *rS);
2023             CR_SET_XER_SO(0, cr_i_zero);
2024           }
2025           else {
2026             /* ment to randomly to store, we never do! */       
2027             CR_SET_XER_SO(0, 0);
2028           }
2029           RESERVE = 0;
2030         }
2031         else {
2032           CR_SET_XER_SO(0, 0);
2033         }
2034 0.31,6.RS,11.RA,16.RB,21.214,31.1:X:64::Store Doubleword Conditional Indexed
2035         unsigned_word b;
2036         unsigned_word EA;
2037         if (RA == 0) b = 0;
2038         else         b = *rA;
2039         EA = b + *rB;
2040         if (RESERVE) {
2041           if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/)
2042               && /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 8)) {
2043             STORE(EA, 8, *rS);
2044             CR_SET_XER_SO(0, cr_i_zero);
2045           }
2046           else {
2047             /* ment to randomly to store, we never do */        
2048             CR_SET_XER_SO(0, 0);
2049           }
2050           RESERVE = 0;
2051         }
2052         else {
2053           CR_SET_XER_SO(0, 0);
2054         }
2055
2056 0.31,6./,11./,16./,21.598,31./:X::sync:Synchronize
2057 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2058 *603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
2059 *603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
2060 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  1,  0
2061         /* do nothing */
2062
2063
2064 #
2065 # I.3.3.9 Fixed-Point Arithmetic Instructions
2066 #
2067
2068 0.14,6.RT,11.RA,16.SI:D:T::Add Immediate
2069 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2070 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2071 *603e:PPC_UNIT_IU,    PPC_UNIT_SRU,   1,  1,  0
2072 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2073         if (RA_is_0) {
2074           *rT = EXTS(SI);
2075           ppc_insn_int0(my_index, processor, cpu_model(processor), rT, 0/*Rc*/);
2076         }
2077         else {
2078           *rT = *rA + EXTS(SI);
2079           ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
2080         }
2081
2082 0.15,6.RT,11.RA,16.SI:D:::Add Immediate Shifted
2083 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2084 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2085 *603e:PPC_UNIT_IU,    PPC_UNIT_SRU,   1,  1,  0
2086 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2087         if (RA_is_0) {
2088           *rT = EXTS(SI) << 16;
2089           ppc_insn_int0(my_index, processor, cpu_model(processor), rT, 0/*Rc*/);
2090         }
2091         else {
2092           *rT = *rA + (EXTS(SI) << 16);
2093           ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
2094         }
2095
2096 0.31,6.RT,11.RA,16.RB,21.OE,22.266,31.Rc:XO:::Add
2097 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2098 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2099 *603e:PPC_UNIT_IU,    PPC_UNIT_SRU,   1,  1,  0
2100 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2101         ALU_BEGIN(*rA);
2102         ALU_ADD(*rB);
2103         ALU_END(*rT, 0/*CA*/, OE, Rc);
2104         ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2105
2106 0.31,6.RT,11.RA,16.RB,21.OE,22.40,31.Rc:XO:::Subtract From
2107 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2108 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2109 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2110 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2111         ALU_BEGIN(*rA);
2112         ALU_NOT;
2113         ALU_ADD(*rB);
2114         ALU_ADD(1);
2115         ALU_END(*rT, 0/*CA*/, OE, Rc);
2116         ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2117
2118 0.12,6.RT,11.RA,16.SI:D:::Add Immediate Carrying
2119 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2120 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2121 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2122 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2123         ALU_BEGIN(*rA);
2124         ALU_ADD(EXTS(SI));
2125         ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
2126         ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
2127
2128 0.13,6.RT,11.RA,16.SI:D:::Add Immediate Carrying and Record
2129 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2130 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2131 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2132 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2133         ALU_BEGIN(*rA);
2134         ALU_ADD(EXTS(SI));
2135         ALU_END(*rT, 1/*CA*/, 0/*OE*/, 1/*Rc*/);
2136         ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 1/*Rc*/);
2137
2138 0.8,6.RT,11.RA,16.SI:D:::Subtract From Immediate Carrying
2139 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2140 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2141 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2142 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2143         ALU_BEGIN(*rA);
2144         ALU_NOT;
2145         ALU_ADD(EXTS(SI));
2146         ALU_ADD(1);
2147         ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
2148         ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
2149
2150 0.31,6.RT,11.RA,16.RB,21.OE,22.10,31.Rc:XO:::Add Carrying
2151 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2152 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2153 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2154 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2155         ALU_BEGIN(*rA);
2156         ALU_ADD(*rB);
2157         ALU_END(*rT, 1/*CA*/, OE, Rc);
2158         ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2159
2160 0.31,6.RT,11.RA,16.RB,21.OE,22.8,31.Rc:XO:::Subtract From Carrying
2161 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2162 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2163 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2164 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2165         /* RT <- ~RA + RB + 1 === RT <- RB - RA */
2166         ALU_BEGIN(*rA);
2167         ALU_NOT;
2168         ALU_ADD(*rB);
2169         ALU_ADD(1);
2170         ALU_END(*rT, 1/*CA*/, OE, Rc);
2171         ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2172
2173 0.31,6.RT,11.RA,16.RB,21.OE,22.138,31.Rc:XO:::Add Extended
2174 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2175 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2176 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2177 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2178         ALU_BEGIN(*rA);
2179         ALU_ADD(*rB);
2180         ALU_ADD_CA;
2181         ALU_END(*rT, 1/*CA*/, OE, Rc);
2182         ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2183
2184 0.31,6.RT,11.RA,16.RB,21.OE,22.136,31.Rc:XO:::Subtract From Extended
2185 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2186 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2187 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2188 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2189         ALU_BEGIN(*rA);
2190         ALU_NOT;
2191         ALU_ADD(*rB);
2192         ALU_ADD_CA;
2193         ALU_END(*rT, 1/*CA*/, OE, Rc);
2194         ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2195
2196 0.31,6.RT,11.RA,16./,21.OE,22.234,31.Rc:XO:::Add to Minus One Extended
2197 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2198 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2199 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2200 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2201 #       ALU_BEGIN(*rA);
2202 #       ALU_ADD_CA;
2203 #       ALU_SUB(1);
2204 #       ALU_END(*rT, 1/*CA*/, OE, Rc);
2205
2206 0.31,6.RT,11.RA,16./,21.OE,22.232,31.Rc:XO:::Subtract From Minus One Extended
2207 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2208 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2209 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2210 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2211 #       ALU_BEGIN(*rA);
2212 #       ALU_NOT;
2213 #       ALU_ADD_CA;
2214 #       ALU_SUB(1);
2215 #       ALU_END(*rT, 1/*CA*/, OE, Rc);
2216
2217 0.31,6.RT,11.RA,16./,21.OE,22.202,31.Rc:XO::addze:Add to Zero Extended
2218 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2219 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2220 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2221 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2222         ALU_BEGIN(*rA);
2223         ALU_ADD_CA;
2224         ALU_END(*rT, 1/*CA*/, OE, Rc);
2225         ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, Rc);
2226
2227 0.31,6.RT,11.RA,16./,21.OE,22.200,31.Rc:XO:::Subtract from Zero Extended
2228 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2229 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2230 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2231 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2232         ALU_BEGIN(*rA);
2233         ALU_NOT;
2234         ALU_ADD_CA;
2235         ALU_END(*rT, 1/*CA*/, OE, Rc);
2236         ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, Rc);
2237
2238 0.31,6.RT,11.RA,16./,21.OE,22.104,31.Rc:XO:::Negate
2239 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2240 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2241 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2242 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2243         ALU_BEGIN(*rA);
2244         ALU_NOT;
2245         ALU_ADD(1);
2246         ALU_END(*rT,0/*CA*/,OE,Rc);
2247         ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, Rc);
2248
2249 0.7,6.RT,11.RA,16.SI:D::mulli:Multiply Low Immediate
2250 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    5,  5,  0
2251 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
2252 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
2253 *604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  3,  3,  0
2254         signed_word prod = *rA * EXTS(SI);
2255         *rT = prod;
2256         ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
2257
2258 0.31,6.RT,11.RA,16.RB,21.OE,22.233,31.Rc:D:64::Multiply Low Doubleword
2259
2260 0.31,6.RT,11.RA,16.RB,21.OE,22.235,31.Rc:XO::mullw:Multiply Low Word
2261 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    5,  5,  0
2262 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    5,  5,  0
2263 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    5,  5,  0
2264 *604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  4,  4,  0
2265         signed64 a = (signed32)(*rA);
2266         signed64 b = (signed32)(*rB);
2267         signed64 prod = a * b;
2268         signed_word t = prod;
2269         *rT = *rA * *rB;
2270         if (t != prod && OE)
2271           XER |= (xer_overflow | xer_summary_overflow);
2272         CR0_COMPARE(t, 0, Rc);
2273         ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2274
2275 0.31,6.RT,11.RA,16.RB,21./,22.73,31.Rc:XO:64::Multiply High Doubleword
2276
2277 0.31,6.RT,11.RA,16.RB,21./,22.75,31.Rc:XO::mulhw:Multiply High Word
2278 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    5,  5,  0
2279 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    5,  5,  0
2280 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    5,  5,  0
2281 *604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  4,  4,  0
2282         signed64 a = (signed32)(*rA);
2283         signed64 b = (signed32)(*rB);
2284         signed64 prod = a * b;
2285         signed_word t = EXTRACTED64(prod, 0, 31);
2286         *rT = t;
2287         CR0_COMPARE(t, 0, Rc);
2288         ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2289
2290 0.31,6.RT,11.RA,16.RB,21./,22.9,31.Rc:XO:64::Multiply High Doubleword Unsigned
2291
2292 0.31,6.RT,11.RA,16.RB,21./,22.11,31.Rc:XO::milhwu:Multiply High Word Unsigned
2293 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    10, 10, 0
2294 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    6,  6,  0
2295 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    6,  6,  0
2296 *604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  4,  4,  0
2297         unsigned64 a = (unsigned32)(*rA);
2298         unsigned64 b = (unsigned32)(*rB);
2299         unsigned64 prod = a * b;
2300         signed_word t = EXTRACTED64(prod, 0, 31);
2301         *rT = t;
2302         CR0_COMPARE(t, 0, Rc);
2303         ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2304
2305 0.31,6.RT,11.RA,16.RB,21.OE,22.489,31.Rc:XO:64::Divide Doubleword
2306
2307 0.31,6.RT,11.RA,16.RB,21.OE,22.491,31.Rc:XO::divw:Divide Word
2308 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    36, 36, 0
2309 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    37, 37, 0
2310 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    37, 37, 0
2311 *604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  20, 20, 0
2312         signed64 dividend = (signed32)(*rA);
2313         signed64 divisor = (signed32)(*rB);
2314         if (divisor == 0 /* nb 0x8000..0 is sign extended */
2315             || (dividend == 0x80000000 && divisor == -1)) {
2316           if (OE)
2317             XER |= (xer_overflow | xer_summary_overflow);
2318           CR0_COMPARE(0, 0, Rc);
2319         }
2320         else {
2321           signed64 quotent = dividend / divisor;
2322           *rT = quotent;
2323           CR0_COMPARE((signed_word)quotent, 0, Rc);
2324         }
2325         ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2326
2327 0.31,6.RT,11.RA,16.RB,21.OE,22.457,31.Rc:XO:64::Divide Doubleword Unsigned
2328
2329 0.31,6.RT,11.RA,16.RB,21.OE,22.459,31.Rc:XO::divwu:Divide Word Unsigned
2330 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    36, 36, 0
2331 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    37, 37, 0
2332 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    37, 37, 0
2333 *604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  20, 20, 0
2334         unsigned64 dividend = (unsigned32)(*rA);
2335         unsigned64 divisor = (unsigned32)(*rB);
2336         if (divisor == 0) {
2337           if (OE)
2338             XER |= (xer_overflow | xer_summary_overflow);
2339           CR0_COMPARE(0, 0, Rc);
2340         }
2341         else {
2342           unsigned64 quotent = dividend / divisor;
2343           *rT = quotent;
2344           CR0_COMPARE((signed_word)quotent, 0, Rc);
2345         }
2346         ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2347
2348
2349 #
2350 # I.3.3.10 Fixed-Point Compare Instructions
2351 #
2352
2353 0.11,6.BF,9./,10.L,11.RA,16.SI:D:::Compare Immediate
2354 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2355 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2356 *603e:PPC_UNIT_IU,    PPC_UNIT_SRU,   1,  1,  0
2357 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2358         if (!is_64bit_mode && L)
2359           program_interrupt(processor, cia,
2360                             illegal_instruction_program_interrupt);
2361         else {
2362           signed_word a;
2363           signed_word b = EXTS(SI);
2364           if (L == 0)
2365             a = EXTENDED(*rA);
2366           else
2367             a = *rA;
2368           CR_COMPARE(BF, a, b);
2369         }
2370         ppc_insn_int1_cr(my_index, processor, cpu_model(processor), BF, rA);
2371
2372 0.31,6.BF,9./,10.L,11.RA,16.RB,21.0,31./:X:::Compare
2373 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2374 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2375 *603e:PPC_UNIT_IU,    PPC_UNIT_SRU,   1,  1,  0
2376 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2377         if (!is_64bit_mode && L)
2378           program_interrupt(processor, cia,
2379                             illegal_instruction_program_interrupt);
2380         else {
2381           signed_word a;
2382           signed_word b;
2383           if (L == 0) {
2384             a = EXTENDED(*rA);
2385             b = EXTENDED(*rB);
2386           }
2387           else {
2388             a = *rA;
2389             b = *rB;
2390           }
2391           CR_COMPARE(BF, a, b);
2392         }
2393         ppc_insn_int2_cr(my_index, processor, cpu_model(processor), BF, rA, rB);
2394
2395 0.10,6.BF,9./,10.L,11.RA,16.UI:D:::Compare Logical Immediate
2396 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2397 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2398 *603e:PPC_UNIT_IU,    PPC_UNIT_SRU,   1,  1,  0
2399 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2400         if (!is_64bit_mode && L)
2401           program_interrupt(processor, cia,
2402                             illegal_instruction_program_interrupt);
2403         else {
2404           unsigned_word a;
2405           unsigned_word b = UI;
2406           if (L == 0)
2407             a = MASKED(*rA, 32, 63);
2408           else
2409             a = *rA;
2410           CR_COMPARE(BF, a, b);
2411         }
2412         ppc_insn_int1_cr(my_index, processor, cpu_model(processor), BF, rA);
2413
2414 0.31,6.BF,9./,10.L,11.RA,16.RB,21.32,31./:X:::Compare Logical
2415 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2416 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2417 *603e:PPC_UNIT_IU,    PPC_UNIT_SRU,   1,  1,  0
2418 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2419         if (!is_64bit_mode && L)
2420           program_interrupt(processor, cia,
2421                             illegal_instruction_program_interrupt);
2422         else {
2423           unsigned_word a;
2424           unsigned_word b;
2425           if (L == 0) {
2426             a = MASKED(*rA, 32, 63);
2427             b = MASKED(*rB, 32, 63);
2428           }
2429           else {
2430             a = *rA;
2431             b = *rB;
2432           }
2433           CR_COMPARE(BF, a, b);
2434         }
2435         ppc_insn_int2_cr(my_index, processor, cpu_model(processor), BF, rA, rB);
2436
2437
2438 #
2439 # I.3.3.11 Fixed-Point Trap Instructions
2440 #
2441
2442 0.2,6.TO,11.RA,16.SI:D:64::Trap Doubleword Immediate
2443         if (!is_64bit_mode)
2444           program_interrupt(processor, cia,
2445                             illegal_instruction_program_interrupt);
2446         else {
2447           signed_word a = *rA;
2448           signed_word b = EXTS(SI);
2449           if ((a < b && TO{0})
2450               || (a > b && TO{1})
2451               || (a == b && TO{2})
2452               || ((unsigned_word)a < (unsigned_word)b && TO{3})
2453               || ((unsigned_word)a > (unsigned_word)b && TO{4})
2454               )
2455             program_interrupt(processor, cia,
2456                               trap_program_interrupt);
2457         }
2458
2459 0.3,6.TO,11.RA,16.SI:D:::Trap Word Immediate
2460 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2461 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    2,  2,  0
2462 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    2,  2,  0
2463 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2464         signed_word a = EXTENDED(*rA);
2465         signed_word b = EXTS(SI);
2466         if ((a < b && TO{0})
2467             || (a > b && TO{1})
2468             || (a == b && TO{2})
2469             || ((unsigned_word)a < (unsigned_word)b && TO{3})
2470             || ((unsigned_word)a > (unsigned_word)b && TO{4})
2471             )
2472           program_interrupt(processor, cia,
2473                             trap_program_interrupt);
2474
2475 0.31,6.TO,11.RA,16.RB,21.68,31./:X:64::Trap Doubleword
2476         if (!is_64bit_mode)
2477           program_interrupt(processor, cia,
2478                             illegal_instruction_program_interrupt);
2479         else {
2480           signed_word a = *rA;
2481           signed_word b = *rB;
2482           if ((a < b && TO{0})
2483               || (a > b && TO{1})
2484               || (a == b && TO{2})
2485               || ((unsigned_word)a < (unsigned_word)b && TO{3})
2486               || ((unsigned_word)a > (unsigned_word)b && TO{4})
2487               )
2488             program_interrupt(processor, cia,
2489                               trap_program_interrupt);
2490         }
2491
2492 0.31,6.TO,11.RA,16.RB,21.4,31./:X:::Trap Word
2493 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2494 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    2,  2,  0
2495 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    2,  2,  0
2496 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2497         signed_word a = EXTENDED(*rA);
2498         signed_word b = EXTENDED(*rB);
2499         if (TO == 12 && rA == rB) {
2500           ITRACE(trace_breakpoint, ("breakpoint\n"));
2501           cpu_halt(processor, cia, was_trap, 0);
2502         }
2503         else if ((a < b && TO{0})
2504             || (a > b && TO{1})
2505             || (a == b && TO{2})
2506             || ((unsigned_word)a < (unsigned_word)b && TO{3})
2507             || ((unsigned_word)a > (unsigned_word)b && TO{4})
2508             )
2509           program_interrupt(processor, cia,
2510                             trap_program_interrupt);
2511
2512 #
2513 # I.3.3.12 Fixed-Point Logical Instructions
2514 #
2515
2516 0.28,6.RS,11.RA,16.UI:D:::AND Immediate
2517 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2518 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2519 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2520 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2521         *rA = *rS & UI;
2522         CR0_COMPARE(*rA, 0, 1/*Rc*/);
2523         ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, 1/*Rc*/);
2524
2525 0.29,6.RS,11.RA,16.UI:D:::AND Immediate Shifted
2526 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2527 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2528 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2529 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2530         *rA = *rS & (UI << 16);
2531         CR0_COMPARE(*rA, 0, 1/*Rc*/);
2532         ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, 1/*Rc*/);
2533
2534 0.24,6.RS,11.RA,16.UI:D:::OR Immediate
2535 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2536 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2537 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2538 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2539         *rA = *rS | UI;
2540         ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, 0);
2541
2542 0.25,6.RS,11.RA,16.UI:D:::OR Immediate Shifted
2543 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2544 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2545 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2546 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2547         *rA = *rS | (UI << 16);
2548         ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, 0);
2549
2550 0.26,6.RS,11.RA,16.UI:D:::XOR Immediate
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         *rA = *rS ^ UI;
2556         ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, 0);
2557
2558 0.27,6.RS,11.RA,16.UI:D:::XOR Immediate Shifted
2559 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2560 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2561 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2562 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2563         *rA = *rS ^ (UI << 16);
2564         ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, 0);
2565
2566 0.31,6.RS,11.RA,16.RB,21.28,31.Rc:X:::AND
2567 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2568 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2569 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2570 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2571         *rA = *rS & *rB;
2572         CR0_COMPARE(*rA, 0, Rc);
2573         ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
2574
2575 0.31,6.RS,11.RA,16.RB,21.444,31.Rc:X:::OR
2576 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2577 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2578 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2579 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2580         *rA = *rS | *rB;
2581         CR0_COMPARE(*rA, 0, Rc);
2582         ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
2583
2584 0.31,6.RS,11.RA,16.RB,21.316,31.Rc:X:::XOR
2585 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2586 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2587 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2588 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2589         *rA = *rS ^ *rB;
2590         CR0_COMPARE(*rA, 0, Rc);
2591         ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
2592
2593 0.31,6.RS,11.RA,16.RB,21.476,31.Rc:X:::NAND
2594 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2595 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2596 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2597 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2598         *rA = ~(*rS & *rB);
2599         CR0_COMPARE(*rA, 0, Rc);
2600         ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
2601
2602 0.31,6.RS,11.RA,16.RB,21.124,31.Rc:X:::NOR
2603 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2604 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2605 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2606 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2607         *rA = ~(*rS | *rB);
2608         CR0_COMPARE(*rA, 0, Rc);
2609         ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
2610
2611 0.31,6.RS,11.RA,16.RB,21.284,31.Rc:X:::Equivalent
2612 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2613 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2614 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2615 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2616 #       *rA = ~(*rS ^ *rB); /* A === B */
2617 #       CR0_COMPARE(*rA, 0, Rc);
2618
2619 0.31,6.RS,11.RA,16.RB,21.60,31.Rc:X:::AND with Complement
2620 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2621 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2622 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2623 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2624         *rA = *rS & ~*rB;
2625         CR0_COMPARE(*rA, 0, Rc);
2626         ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
2627
2628 0.31,6.RS,11.RA,16.RB,21.412,31.Rc:X:::OR with Complement
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         *rA = *rS | ~*rB;
2634         CR0_COMPARE(*rA, 0, Rc);
2635         ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
2636
2637 0.31,6.RS,11.RA,16./,21.954,31.Rc:X::extsb:Extend Sign Byte
2638 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2639 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2640 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2641 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2642         *rA = (signed_word)(signed8)*rS;
2643         CR0_COMPARE(*rA, 0, Rc);
2644         ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
2645
2646 0.31,6.RS,11.RA,16./,21.922,31.Rc:X::extsh:Extend Sign Half Word
2647 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2648 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2649 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2650 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2651         *rA = (signed_word)(signed16)*rS;
2652         CR0_COMPARE(*rA, 0, Rc);
2653         ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
2654
2655 0.31,6.RS,11.RA,16./,21.986,31.Rc:X:64::Extend Sign Word
2656 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2657 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2658 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2659 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2660 #       *rA = (signed_word)(signed32)*rS;
2661 #       CR0_COMPARE(*rA, 0, Rc);
2662
2663 0.31,6.RS,11.RA,16./,21.58,31.Rc:X:64::Count Leading Zeros Doubleword
2664 #       int count = 0;
2665 #       unsigned64 mask = BIT64(0);
2666 #       unsigned64 source = *rS;
2667 #       while (!(source & mask) && mask != 0) {
2668 #         mask >>= 1;
2669 #         count++;
2670 #       }
2671 #       *rA = count;
2672 #       CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */
2673
2674 0.31,6.RS,11.RA,16./,21.26,31.Rc:X:::Count Leading Zeros Word
2675 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2676 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2677 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2678 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2679         int count = 0;
2680         unsigned32 mask = BIT32(0);
2681         unsigned32 source = *rS;
2682         while (!(source & mask) && mask != 0) {
2683           mask >>= 1;
2684           count++;
2685         }
2686         *rA = count;
2687         CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */
2688
2689
2690 #
2691 # I.3.3.13 Fixed-Point Rotate and Shift Instructions
2692 #
2693
2694 0.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
2695 #       long n = (sh_5 << 4) | sh_0_4;
2696 #       unsigned_word r = ROTL64(*rS, n);
2697 #       long b = (mb_5 << 4) | mb_0_4;
2698 #       unsigned_word m = MASK(b, 63);
2699 #       signed_word result = r & m;
2700 #       *rA = result;
2701 #       CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
2702
2703 0.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
2704 #       long n = (sh_5 << 4) | sh_0_4;
2705 #       unsigned_word r = ROTL64(*rS, n);
2706 #       long e = (me_5 << 4) | me_0_4;
2707 #       unsigned_word m = MASK(0, e);
2708 #       signed_word result = r & m;
2709 #       *rA = result;
2710 #       CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
2711
2712 0.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
2713 #       long n = (sh_5 << 4) | sh_0_4;
2714 #       unsigned_word r = ROTL64(*rS, n);
2715 #       long b = (mb_5 << 4) | mb_0_4;
2716 #       unsigned_word m = MASK(0, (64-n));
2717 #       signed_word result = r & m;
2718 #       *rA = result;
2719 #       CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
2720
2721 0.21,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M:::Rotate Left Word Immediate then AND with Mask
2722 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2723 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2724 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2725 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2726         long n = SH;
2727         unsigned32 s = *rS;
2728         unsigned32 r = ROTL32(s, n);
2729         unsigned32 m = MASK(MB+32, ME+32);
2730         signed_word result = r & m;
2731         *rA = result;
2732         CR0_COMPARE(result, 0, Rc);
2733         ITRACE(trace_alu,
2734                ("n=%d, s=0x%x, r=0x%x, m=0x%x, result=0x%x, cr=0x%x\n",
2735                 n, s, r, m, result, CR));
2736         ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
2737
2738 0.30,6.RS,11.RA,16.RB,21.mb,27.8,31.Rc:MDS:64::Rotate Left Doubleword then Clear Left
2739 #       long n = MASKED(*rB, 58, 63);
2740 #       unsigned_word r = ROTL64(*rS, n);
2741 #       long b = (mb_5 << 4) | mb_0_4;
2742 #       unsigned_word m = MASK(b, 63);
2743 #       signed_word result = r & m;
2744 #       *rA = result;
2745 #       CR0_COMPARE(result, 0, Rc);
2746
2747 0.30,6.RS,11.RA,16.RB,21.me,27.9,31.Rc:MDS:64::Rotate Left Doubleword then Clear Right
2748 #       long n = MASKED(*rB, 58, 63);
2749 #       unsigned_word r = ROTL64(*rS, n);
2750 #       long e = (me_5 << 4) | me_0_4;
2751 #       unsigned_word m = MASK(0, e);
2752 #       signed_word result = r & m;
2753 #       *rA = result;
2754 #       CR0_COMPARE(result, 0, Rc);
2755
2756 0.23,6.RS,11.RA,16.RB,21.MB,26.ME,31.Rc:M:::Rotate Left Word then AND with Mask
2757 #       long n = MASKED(*rB, 59, 63);
2758 #       unsigned32 r = ROTL32(*rS, n);
2759 #       unsigned32 m = MASK(MB+32, ME+32);
2760 #       signed_word result = r & m;
2761 #       *rA = result;
2762 #       CR0_COMPARE(result, 0, Rc);
2763
2764 0.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
2765 #       long n = (sh_5 << 4) | sh_0_4;
2766 #       unsigned_word r = ROTL64(*rS, n);
2767 #       long b = (mb_5 << 4) | mb_0_4;
2768 #       unsigned_word m = MASK(b, (64-n));
2769 #       signed_word result = (r & m) | (*rA & ~m)
2770 #       *rA = result;
2771 #       CR0_COMPARE(result, 0, Rc);
2772
2773 0.20,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M::rlwimi:Rotate Left Word Immediate then Mask Insert
2774 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2775 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2776 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2777 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2778         long n = SH;
2779         unsigned32 r = ROTL32(*rS, n);
2780         unsigned32 m = MASK(MB+32, ME+32);
2781         signed_word result = (r & m) | (*rA & ~m);
2782         *rA = result;
2783         ITRACE(trace_alu, (": n=%d *rS=0x%x r=0x%x m=0x%x result=0x%x\n",
2784                            n, *rS, r, m, result));
2785         CR0_COMPARE(result, 0, Rc);
2786         ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
2787
2788
2789 0.31,6.RS,11.RA,16.RB,21.27,31.Rc:X:64::Shift Left Doubleword
2790
2791 0.31,6.RS,11.RA,16.RB,21.24,31.Rc:X:::Shift Left Word
2792 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2793 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2794 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2795 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2796         int n = MASKED(*rB, 59, 63);
2797         unsigned32 source = *rS;
2798         signed_word shifted;
2799         if (n < 32)
2800           shifted = (source << n);
2801         else
2802           shifted = 0;
2803         *rA = shifted;
2804         CR0_COMPARE(shifted, 0, Rc);
2805         ITRACE(trace_alu,
2806                ("n=%d, source=0x%x, shifted=0x%x\n",
2807                 n, source, shifted));
2808         ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
2809
2810 0.31,6.RS,11.RA,16.RB,21.539,31.Rc:X:64::Shift Right Doubleword
2811
2812 0.31,6.RS,11.RA,16.RB,21.536,31.Rc:X:::Shift Right Word
2813 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2814 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2815 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2816 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2817         int n = MASKED(*rB, 59, 63);
2818         unsigned32 source = *rS;
2819         signed_word shifted;
2820         if (n < 32)
2821           shifted = (source >> n);
2822         else
2823           shifted = 0;
2824         *rA = shifted;
2825         CR0_COMPARE(shifted, 0, Rc);
2826         ITRACE(trace_alu, \
2827                ("n=%d, source=0x%x, shifted=0x%x\n",
2828                 n, source, shifted));
2829         ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
2830
2831 0.31,6.RS,11.RA,16.sh_0_4,21.413,30.sh_5,31.Rc:XS:64::Shift Right Algebraic Doubleword Immediate
2832
2833 0.31,6.RS,11.RA,16.SH,21.824,31.Rc:X:::Shift Right Algebraic Word Immediate
2834 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2835 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2836 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2837 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2838         int n = SH;
2839         signed_word r = ROTL32(*rS, /*64*/32-n);
2840         signed_word m = MASK(n+32, 63);
2841         int S = MASKED(*rS, 32, 32);
2842         signed_word shifted = (r & m) | (S ? ~m : 0);
2843         *rA = shifted;
2844         if (S && ((r & ~m) & MASK(32, 63)) != 0)
2845           XER |= xer_carry;
2846         else
2847           XER &= ~xer_carry;
2848         CR0_COMPARE(shifted, 0, Rc);
2849         ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
2850
2851 0.31,6.RS,11.RA,16.RB,21.794,31.Rc:X:64::Shift Right Algebraic Doubleword
2852
2853 0.31,6.RS,11.RA,16.RB,21.792,31.Rc:X:::Shift Right Algebraic Word
2854 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2855 *603: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2856 *603e:PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2857 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1,  1,  0
2858         int n = MASKED(*rB, 58, 63);
2859         int shift = (n >= 31 ? 31 : n);
2860         signed32 source = (signed32)*rS; /* signed to keep sign bit */
2861         signed32 shifted = source >> shift;
2862         unsigned32 mask = ((unsigned32)-1) >> (31-shift);
2863         *rA = (signed_word)shifted; /* if 64bit will sign extend */
2864         if (source < 0 && (source & mask))
2865           XER |= xer_carry;
2866         else
2867           XER &= ~xer_carry;
2868         CR0_COMPARE(shifted, 0, Rc);
2869         ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
2870
2871 #
2872 # I.3.3.14 Move to/from System Register Instructions
2873 #
2874
2875 0.31,6.RS,11.spr,21.467,31./:XFX::mtspr %SPR, %RS:Move to Special Purpose Register
2876 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2877 *603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   2,  2,  0
2878 *603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   2,  2,  0
2879 *604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  1,  1,  0
2880         int n = (spr{5:9} << 5) | spr{0:4};
2881         if (spr{0} && IS_PROBLEM_STATE(processor))
2882           program_interrupt(processor, cia,
2883                             privileged_instruction_program_interrupt);
2884         else if (!spr_is_valid(n)
2885                  || spr_is_readonly(n))
2886           program_interrupt(processor, cia,
2887                             illegal_instruction_program_interrupt);
2888         else {
2889           spreg new_val = (spr_length(n) == 64
2890                            ? *rS
2891                            : MASKED(*rS, 32, 63));
2892           /* HACK - time base registers need to be updated immediatly */
2893           if (WITH_TIME_BASE) {
2894             signed64 time_base;
2895             switch (n) {
2896             case spr_tbu:
2897               cpu_set_time_base(processor,
2898                                 (MASKED64(cpu_get_time_base(processor), 32, 63)
2899                                  | INSERTED64(new_val, 0, 31)));
2900               break;
2901             case spr_tbl:
2902               cpu_set_time_base(processor,
2903                                 (MASKED64(cpu_get_time_base(processor), 0, 31)
2904                                  | INSERTED64(new_val, 32, 63)));
2905               break;
2906             case spr_dec:
2907               cpu_set_decrementer(processor, new_val);
2908               break;
2909             default:
2910               SPREG(n) = new_val;
2911               break;
2912             }
2913           }
2914           else {
2915             SPREG(n) = new_val;
2916           }
2917         }
2918         ppc_insn_to_spr(my_index, processor, cpu_model(processor), n, rS);
2919
2920 0.31,6.RT,11.spr,21.339,31./:XFX::mfspr %RT, %SPR:Move from Special Purpose Register
2921 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2922 *603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
2923 *603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
2924 *604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  3,  3,  0
2925         int n = (spr{5:9} << 5) | spr{0:4};
2926         if (spr{0} && IS_PROBLEM_STATE(processor))
2927           program_interrupt(processor, cia,
2928                             privileged_instruction_program_interrupt);
2929         else if (!spr_is_valid(n))
2930           program_interrupt(processor, cia,
2931                             illegal_instruction_program_interrupt);
2932         else {
2933           /* HACK - some SPR's need to get their value extracted specially */
2934           *rT = SPREG(n);
2935         }
2936         ppc_insn_from_spr(my_index, processor, cpu_model(processor), rT, n);
2937
2938 # FIXME: 604 uses SCIU{1,2} if only one bit is being set
2939 0.31,6.RS,11./,12.FXM,20./,21.144,31./:XFX::mtfcr:Move to Condition Register Fields
2940 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    2,  2,  0
2941 *603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
2942 *603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
2943 *604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  1,  1,  0
2944         if (FXM == 0xff) {
2945           CR = *rS;
2946         }
2947         else {
2948           unsigned_word mask = 0;
2949           unsigned_word f;
2950           for (f = 0; f < 8; f++) {
2951             if (FXM & (0x80 >> f))
2952               mask |= (0xf << 4*(7-f));
2953           }
2954           CR = (MASKED(*rS, 32, 63) & mask) | (CR & ~mask);
2955         }
2956
2957 0.31,6.BF,9./,11./,16./,21.512,31./:X:::Move to Condition Register from XER
2958
2959 0.31,6.RT,11./,16./,21.19,31./:X:::Move From Condition Register
2960 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
2961 *603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
2962 *603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
2963 *604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  3,  3,  0
2964         *rT = (unsigned32)CR;
2965
2966 #
2967 # I.4.6.2 Floating-Point Load Instructions
2968 #
2969
2970 0.48,6.FRT,11.RA,16.D:D:f:lfs:Load Floating-Point Single
2971 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
2972 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2973 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2974 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
2975         unsigned_word b;
2976         unsigned_word EA;
2977         if (RA == 0) b = 0;
2978         else         b = *rA;
2979         EA = b + EXTS(D);
2980         *frT = DOUBLE(MEM(unsigned, EA, 4));
2981
2982 0.31,6.FRT,11.RA,16.RB,21.535,31./:X:f::Load Floating-Point Single Indexed
2983 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
2984 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2985 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2986 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
2987         unsigned_word b;
2988         unsigned_word EA;
2989         if (RA == 0) b = 0;
2990         else         b = *rA;
2991         EA = b + *rB;
2992         *frT = DOUBLE(MEM(unsigned, EA, 4));
2993
2994 0.49,6.FRT,11.RA,16.D:D:f::Load Floating-Point Single with Update
2995 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
2996 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2997 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
2998 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
2999         unsigned_word EA;
3000         if (RA == 0)
3001           program_interrupt(processor, cia,
3002                             illegal_instruction_program_interrupt);
3003         EA = *rA + EXTS(D);
3004         *frT = DOUBLE(MEM(unsigned, EA, 4));
3005         *rA = EA;
3006
3007 0.31,6.FRT,11.RA,16.RB,21.576,31./:X:f::Load Floating-Point Single with Update Indexed
3008 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
3009 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3010 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3011 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3012         unsigned_word EA;
3013         if (RA == 0)
3014           program_interrupt(processor, cia,
3015                             illegal_instruction_program_interrupt);
3016         EA = *rA + *rB;
3017         *frT = DOUBLE(MEM(unsigned, EA, 4));
3018         *rA = EA;
3019
3020 0.50,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double
3021 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
3022 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3023 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3024 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3025         unsigned_word b;
3026         unsigned_word EA;
3027         if (RA == 0) b = 0;
3028         else         b = *rA;
3029         EA = b + EXTS(D);
3030         *frT = MEM(unsigned, EA, 8);
3031
3032 0.31,6.FRT,11.RA,16.RB,21.599,31./:X:f::Load Floating-Point Double Indexed
3033 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
3034 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3035 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3036 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3037         unsigned_word b;
3038         unsigned_word EA;
3039         if (RA == 0) b = 0;
3040         else         b = *rA;
3041         EA = b + *rB;
3042         *frT = MEM(unsigned, EA, 8);
3043
3044 0.51,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double with Update
3045 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
3046 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3047 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3048 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3049         unsigned_word EA;
3050         if (RA == 0)
3051           program_interrupt(processor, cia,
3052                             illegal_instruction_program_interrupt);
3053         EA = *rA + EXTS(D);
3054         *frT = MEM(unsigned, EA, 8);
3055         *rA = EA;
3056
3057 0.31,6.FRT,11.RA,16.RB,21.631,31./:X:f::Load Floating-Point Double with Update Indexed
3058 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    3,  3,  0
3059 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3060 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3061 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3062         unsigned_word EA;
3063         if (RA == 0)
3064           program_interrupt(processor, cia,
3065                             illegal_instruction_program_interrupt);
3066         EA = *rA + *rB;
3067         *frT = MEM(unsigned, EA, 8);
3068         *rA = EA;
3069
3070
3071 #
3072 # I.4.6.3 Floating-Point Store Instructions
3073 #
3074
3075 0.52,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single
3076 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3077 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3078 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3079 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3080         unsigned_word b;
3081         unsigned_word EA;
3082         if (RA == 0) b = 0;
3083         else         b = *rA;
3084         EA = b + EXTS(D);
3085         STORE(EA, 4, SINGLE(*frS));
3086
3087 0.31,6.FRS,11.RA,16.RB,21.663,31./:X:f::Store Floating-Point Single Indexed
3088 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3089 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3090 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3091 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3092         unsigned_word b;
3093         unsigned_word EA;
3094         if (RA == 0) b = 0;
3095         else         b = *rA;
3096         EA = b + *rB;
3097         STORE(EA, 4, SINGLE(*frS));
3098
3099 0.53,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single with Update
3100 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3101 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3102 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3103 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3104         unsigned_word EA;
3105         if (RA == 0)
3106           program_interrupt(processor, cia,
3107                             illegal_instruction_program_interrupt);
3108         EA = *rA + EXTS(D);
3109         STORE(EA, 4, SINGLE(*frS));
3110         *rA = EA;
3111
3112 0.31,6.FRS,11.RA,16.RB,21.695,31./:X:f::Store Floating-Point Single with Update Indexed
3113 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3114 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3115 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3116 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3117         unsigned_word EA;
3118         if (RA == 0)
3119           program_interrupt(processor, cia,
3120                             illegal_instruction_program_interrupt);
3121         EA = *rA + *rB;
3122         STORE(EA, 4, SINGLE(*frS));
3123         *rA = EA;
3124
3125 0.54,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double
3126 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3127 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3128 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3129 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3130         unsigned_word b;
3131         unsigned_word EA;
3132         if (RA == 0) b = 0;
3133         else         b = *rA;
3134         EA = b + EXTS(D);
3135         STORE(EA, 8, *frS);
3136
3137 0.31,6.FRS,11.RA,16.RB,21.727,31./:X:f::Store Floating-Point Double Indexed
3138 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3139 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3140 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3141 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3142         unsigned_word b;
3143         unsigned_word EA;
3144         if (RA == 0) b = 0;
3145         else         b = *rA;
3146         EA = b + *rB;
3147         STORE(EA, 8, *frS);
3148
3149 0.55,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double with Update
3150 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3151 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3152 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3153 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3154         unsigned_word EA;
3155         if (RA == 0)
3156           program_interrupt(processor, cia,
3157                             illegal_instruction_program_interrupt);
3158         EA = *rA + EXTS(D);
3159         STORE(EA, 8, *frS);
3160         *rA = EA;
3161
3162 0.31,6.FRS,11.RA,16.RB,21.759,31./:X:f::Store Floating-Point Double with Update Indexed
3163 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3164 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3165 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  2,  0
3166 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3167         unsigned_word EA;
3168         if (RA == 0)
3169           program_interrupt(processor, cia,
3170                             illegal_instruction_program_interrupt);
3171         EA = *rA + *rB;
3172         STORE(EA, 8, *frS);
3173         *rA = EA;
3174
3175
3176 #
3177 # I.4.6.4 Floating-Point Move Instructions
3178 #
3179
3180 0.63,6.FRT,11./,16.FRB,21.72,31.Rc:X:f::Floating Move Register
3181 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3182 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3183 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3184 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3185         *frT = *frB;
3186         CR1_UPDATE(Rc);
3187
3188 0.63,6.FRT,11./,16.FRB,21.40,31.Rc:X:f::Floating Negate
3189 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3190 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3191 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3192 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3193         *frT = *frB ^ BIT64(0);
3194         CR1_UPDATE(Rc);
3195
3196 0.63,6.FRT,11./,16.FRB,21.264,31.Rc:X:f::Floating Absolute Value
3197 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3198 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3199 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3200 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3201         *frT = *frB & ~BIT64(0);
3202         CR1_UPDATE(Rc);
3203
3204 0.63,6.FRT,11./,16.FRB,21.136,31.Rc:X:f::Floating Negative Absolute Value
3205 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3206 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3207 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3208 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3209         *frT = *frB | BIT64(0);
3210         CR1_UPDATE(Rc);
3211
3212
3213
3214 #
3215 # I.4.6.5 Floating-Point Arithmetic Instructions
3216 #
3217
3218 0.63,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadd:Floating Add
3219 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3220 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3221 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3222 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3223         FPSCR_BEGIN;
3224         if (is_invalid_operation(processor, cia,
3225                                  *frA, *frB,
3226                                  fpscr_vxsnan | fpscr_vxisi,
3227                                  0, /*single?*/
3228                                  0) /*negate?*/) {
3229           invalid_arithemetic_operation(processor, cia,
3230                                         frT, *frA, *frB, 0,
3231                                         0, /*instruction_is_frsp*/
3232                                         0, /*instruction_is_convert_to_64bit*/
3233                                         0, /*instruction_is_convert_to_32bit*/
3234                                         0); /*single-precision*/
3235         }
3236         else {
3237           /*HACK!*/
3238           double s = *(double*)frA + *(double*)frB;
3239           *(double*)frT = s;
3240         }
3241         FPSCR_END(Rc);
3242
3243 0.59,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadds:Floating Add Single
3244 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3245 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3246 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3247 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3248         FPSCR_BEGIN;
3249         if (is_invalid_operation(processor, cia,
3250                                  *frA, *frB,
3251                                  fpscr_vxsnan | fpscr_vxisi,
3252                                  1, /*single?*/
3253                                  0) /*negate?*/) {
3254           invalid_arithemetic_operation(processor, cia,
3255                                         frT, *frA, *frB, 0,
3256                                         0, /*instruction_is_frsp*/
3257                                         0, /*instruction_is_convert_to_64bit*/
3258                                         0, /*instruction_is_convert_to_32bit*/
3259                                         1); /*single-precision*/
3260         }
3261         else {
3262           /*HACK!*/
3263           float s = *(double*)frA + *(double*)frB;
3264           *(double*)frT = s;
3265         }
3266         FPSCR_END(Rc);
3267
3268 0.63,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsub:Floating Subtract
3269 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3270 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3271 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3272 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3273         FPSCR_BEGIN;
3274         if (is_invalid_operation(processor, cia,
3275                                  *frA, *frB,
3276                                  fpscr_vxsnan | fpscr_vxisi,
3277                                  0, /*single?*/
3278                                  1) /*negate?*/) {
3279           invalid_arithemetic_operation(processor, cia,
3280                                         frT, *frA, *frB, 0,
3281                                         0, /*instruction_is_frsp*/
3282                                         0, /*instruction_is_convert_to_64bit*/
3283                                         0, /*instruction_is_convert_to_32bit*/
3284                                         0); /*single-precision*/
3285         }
3286         else {
3287           /*HACK!*/
3288           double s = *(double*)frA - *(double*)frB;
3289           *(double*)frT = s;
3290         }
3291         FPSCR_END(Rc);
3292
3293 0.59,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsubs:Floating Subtract Single
3294 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3295 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3296 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3297 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3298         FPSCR_BEGIN;
3299         if (is_invalid_operation(processor, cia,
3300                                  *frA, *frB,
3301                                  fpscr_vxsnan | fpscr_vxisi,
3302                                  1, /*single?*/
3303                                  1) /*negate?*/) {
3304           invalid_arithemetic_operation(processor, cia,
3305                                         frT, *frA, *frB, 0,
3306                                         0, /*instruction_is_frsp*/
3307                                         0, /*instruction_is_convert_to_64bit*/
3308                                         0, /*instruction_is_convert_to_32bit*/
3309                                         1); /*single-precision*/
3310         }
3311         else {
3312           /*HACK!*/
3313           float s = *(double*)frA - *(double*)frB;
3314           *(double*)frT = s;
3315         }
3316         FPSCR_END(Rc);
3317
3318 0.63,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmul:Floating Multiply
3319 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   5,  5,  0
3320 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
3321 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
3322 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3323         FPSCR_BEGIN;
3324         if (is_invalid_operation(processor, cia,
3325                                  *frA, *frC,
3326                                  fpscr_vxsnan | fpscr_vximz,
3327                                  0, /*single?*/
3328                                  0) /*negate?*/) {
3329           invalid_arithemetic_operation(processor, cia,
3330                                         frT, *frA, 0, *frC,
3331                                         0, /*instruction_is_frsp*/
3332                                         0, /*instruction_is_convert_to_64bit*/
3333                                         0, /*instruction_is_convert_to_32bit*/
3334                                         0); /*single-precision*/
3335         }
3336         else {
3337           /*HACK!*/
3338           double s = *(double*)frA * *(double*)frC;
3339           *(double*)frT = s;
3340         }
3341         FPSCR_END(Rc);
3342
3343 0.59,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmuls:Floating Multiply Single
3344 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3345 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3346 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3347 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3348         FPSCR_BEGIN;
3349         if (is_invalid_operation(processor, cia,
3350                                  *frA, *frC,
3351                                  fpscr_vxsnan | fpscr_vximz,
3352                                  1, /*single?*/
3353                                  0) /*negate?*/) {
3354           invalid_arithemetic_operation(processor, cia,
3355                                         frT, *frA, 0, *frC,
3356                                         0, /*instruction_is_frsp*/
3357                                         0, /*instruction_is_convert_to_64bit*/
3358                                         0, /*instruction_is_convert_to_32bit*/
3359                                         1); /*single-precision*/
3360         }
3361         else {
3362           /*HACK!*/
3363           float s = *(double*)frA * *(double*)frC;
3364           *(double*)frT = s;
3365         }
3366         FPSCR_END(Rc);
3367
3368 0.63,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdiv:Floating Divide
3369 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   31, 31, 0
3370 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   33, 33, 0
3371 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   33, 33, 0
3372 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   32, 32, 0
3373         FPSCR_BEGIN;
3374         if (is_invalid_operation(processor, cia,
3375                                  *frA, *frB,
3376                                  fpscr_vxsnan | fpscr_vxzdz,
3377                                  0, /*single?*/
3378                                  0) /*negate?*/) {
3379           invalid_arithemetic_operation(processor, cia,
3380                                         frT, *frA, *frB, 0,
3381                                         0, /*instruction_is_frsp*/
3382                                         0, /*instruction_is_convert_to_64bit*/
3383                                         0, /*instruction_is_convert_to_32bit*/
3384                                         0); /*single-precision*/
3385         }
3386         else {
3387           /*HACK!*/
3388           double s = *(double*)frA / *(double*)frB;
3389           *(double*)frT = s;
3390         }
3391         FPSCR_END(Rc);
3392
3393 0.59,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdivs:Floating Divide Single
3394 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   17, 17, 0
3395 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   18, 18, 0
3396 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   18, 18, 0
3397 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   18, 18, 0
3398         FPSCR_BEGIN;
3399         if (is_invalid_operation(processor, cia,
3400                                  *frA, *frB,
3401                                  fpscr_vxsnan | fpscr_vxzdz,
3402                                  1, /*single?*/
3403                                  0) /*negate?*/) {
3404           invalid_arithemetic_operation(processor, cia,
3405                                         frT, *frA, *frB, 0,
3406                                         0, /*instruction_is_frsp*/
3407                                         0, /*instruction_is_convert_to_64bit*/
3408                                         0, /*instruction_is_convert_to_32bit*/
3409                                         1); /*single-precision*/
3410         }
3411         else {
3412           /*HACK!*/
3413           float s = *(double*)frA / *(double*)frB;
3414           *(double*)frT = s;
3415         }
3416         FPSCR_END(Rc);
3417
3418 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f:fmadd:Floating Multiply-Add
3419 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   5,  5,  0
3420 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
3421 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
3422 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3423         FPSCR_BEGIN;
3424         double product; /*HACK! - incorrectly loosing precision ... */
3425         /* compute the multiply */
3426         if (is_invalid_operation(processor, cia,
3427                                  *frA, *frC,
3428                                  fpscr_vxsnan | fpscr_vximz,
3429                                  0, /*single?*/
3430                                  0) /*negate?*/) {
3431           invalid_arithemetic_operation(processor, cia,
3432                                         (unsigned64*)&product, *frA, 0, *frC,
3433                                         0, /*instruction_is_frsp*/
3434                                         0, /*instruction_is_convert_to_64bit*/
3435                                         0, /*instruction_is_convert_to_32bit*/
3436                                         0); /*single-precision*/
3437         }
3438         else {
3439           /*HACK!*/
3440           product = *(double*)frA * *(double*)frC;
3441         }
3442         /* compute the add */
3443         if (is_invalid_operation(processor, cia,
3444                                  product, *frB,
3445                                  fpscr_vxsnan | fpscr_vxisi,
3446                                  0, /*single?*/
3447                                  0) /*negate?*/) {
3448           invalid_arithemetic_operation(processor, cia,
3449                                         frT, product, *frB, 0,
3450                                         0, /*instruction_is_frsp*/
3451                                         0, /*instruction_is_convert_to_64bit*/
3452                                         0, /*instruction_is_convert_to_32bit*/
3453                                         0); /*single-precision*/
3454         }
3455         else {
3456           /*HACK!*/
3457           double s = product + *(double*)frB;
3458           *(double*)frT = s;
3459         }
3460         FPSCR_END(Rc);
3461
3462 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f::Floating Multiply-Add Single
3463 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3464 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3465 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3466 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3467
3468 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract
3469 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   5,  5,  0
3470 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
3471 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
3472 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3473
3474 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract Single
3475 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3476 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3477 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3478 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3479
3480 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add
3481 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   5,  5,  0
3482 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
3483 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
3484 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3485
3486 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add Single
3487 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3488 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3489 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3490 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3491
3492 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract
3493 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   5,  5,  0
3494 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
3495 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   2,  4,  0
3496 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3497
3498 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract Single
3499 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3500 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3501 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3502 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3503
3504
3505 #
3506 # I.4.6.6 Floating-Point Rounding and Conversion Instructions
3507 #
3508
3509 0.63,6.FRT,11./,16.FRB,21.12,31.Rc:X:f::Floating Round to Single-Precision
3510 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3511 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3512 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3513 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3514         int sign;
3515         int exp;
3516         unsigned64 frac_grx;
3517         /* split off cases for what to do */
3518         if (EXTRACTED64(*frB, 1, 11) < 897
3519             && EXTRACTED64(*frB, 1, 63) > 0) {
3520             if ((FPSCR & fpscr_ue) == 0) goto Disabled_Exponent_Underflow;
3521             if ((FPSCR & fpscr_ue) != 0) goto Enabled_Exponent_Underflow;
3522         }
3523         if (EXTRACTED64(*frB, 1, 11) > 1150
3524             && EXTRACTED64(*frB, 1, 11) < 2047) {
3525             if ((FPSCR & fpscr_oe) == 0) goto Disabled_Exponent_Overflow;
3526             if ((FPSCR & fpscr_oe) != 0) goto Enabled_Exponent_Overflow;
3527         }
3528         if (EXTRACTED64(*frB, 1, 11) > 896
3529             && EXTRACTED64(*frB, 1, 11) < 1151) goto Normal_Operand;
3530         if (EXTRACTED64(*frB, 1, 63) == 0) goto Zero_Operand;
3531         if (EXTRACTED64(*frB, 1, 11) == 2047) {
3532           if (EXTRACTED64(*frB, 12, 63) == 0) goto Infinity_Operand;
3533           if (EXTRACTED64(*frB, 12, 12) == 1) goto QNaN_Operand;
3534           if (EXTRACTED64(*frB, 12, 12) == 0
3535               && EXTRACTED64(*frB, 13, 63) > 0) goto SNaN_Operand;
3536         }
3537         /* handle them */
3538         Disabled_Exponent_Underflow:
3539           sign = EXTRACTED64(*frB, 0, 0);
3540           if (EXTRACTED64(*frB, 1, 11) == 0) {
3541             exp = -1022;
3542             frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
3543           }
3544           if (EXTRACTED64(*frB, 1, 11) > 0) {
3545             exp = EXTRACTED64(*frB, 1, 11) - 1023;
3546             frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
3547           }
3548           Denormalize_Operand:
3549             /* G|R|X == zero from above */
3550             while (exp < -126) {
3551               exp = exp - 1;
3552               frac_grx = (INSERTED64(EXTRACTED64(frac_grx, 0, 54), 1, 55)
3553                           | MASKED64(frac_grx, 55, 55));
3554             }
3555           FPSCR_SET_UX(EXTRACTED64(frac_grx, 24, 55) > 0);
3556           Round_Single(processor, sign, &exp, &frac_grx);
3557           FPSCR_SET_XX(FPSCR & fpscr_fi);
3558           if (EXTRACTED64(frac_grx, 0, 52) == 0) {
3559             *frT = INSERTED64(sign, 0, 0);
3560             if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
3561             if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
3562           }
3563           if (EXTRACTED64(frac_grx, 0, 52) > 0) {
3564             if (EXTRACTED64(frac_grx, 0, 0) == 1) {
3565               if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
3566               if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
3567             }
3568             if (EXTRACTED64(frac_grx, 0, 0) == 0) {
3569               if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_denormalized_number);
3570               if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_denormalized_number);
3571             }
3572             /*Normalize_Operand:*/
3573               while (EXTRACTED64(frac_grx, 0, 0) == 0) {
3574                 exp = exp - 1;
3575                 frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1,  52), 0, 51);
3576               }
3577             *frT = (INSERTED64(sign, 0, 0)
3578                     | INSERTED64(exp + 1023, 1, 11)
3579                     | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
3580           }
3581           goto Done;
3582         Enabled_Exponent_Underflow:
3583           FPSCR_SET_UX(1);
3584           sign = EXTRACTED64(*frB, 0, 0);
3585           if (EXTRACTED64(*frB, 1, 11) == 0) {
3586             exp = -1022;
3587             frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
3588           }
3589           if (EXTRACTED64(*frB, 1, 11) > 0) {
3590             exp = EXTRACTED64(*frB, 1, 11) - 1023;
3591             frac_grx = (BIT64(0) |
3592                         INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52));
3593           }
3594           /*Normalize_Operand:*/
3595             while (EXTRACTED64(frac_grx, 0, 0) == 0) {
3596               exp = exp - 1;
3597               frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1, 52), 0, 51);
3598             }
3599           Round_Single(processor, sign, &exp, &frac_grx);
3600           FPSCR_SET_XX(FPSCR & fpscr_fi);
3601           exp = exp + 192;
3602           *frT = (INSERTED64(sign, 0, 0)
3603                   | INSERTED64(exp + 1023, 1, 11)
3604                   | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
3605           if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
3606           if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
3607           goto Done;
3608         Disabled_Exponent_Overflow:
3609           FPSCR_SET_OX(1);
3610           if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
3611             if (EXTRACTED64(*frB, 0, 0) == 0) {
3612               *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
3613               FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
3614             }
3615             if (EXTRACTED64(*frB, 0, 0) == 1) {
3616               *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
3617               FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
3618             }
3619           }
3620           if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_zero) {
3621             if (EXTRACTED64(*frB, 0, 0) == 0) {
3622               *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
3623               FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
3624             }
3625             if (EXTRACTED64(*frB, 0, 0) == 1) {
3626               *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
3627               FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
3628             }
3629           }
3630           if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_pos_infinity) {
3631             if (EXTRACTED64(*frB, 0, 0) == 0) {
3632               *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
3633               FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
3634             }
3635             if (EXTRACTED64(*frB, 0, 0) == 1) {
3636               *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
3637               FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
3638             }
3639           }
3640           if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_neg_infinity) {
3641             if (EXTRACTED64(*frB, 0, 0) == 0) {
3642               *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
3643               FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
3644             }
3645             if (EXTRACTED64(*frB, 0, 0) == 1) {
3646               *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
3647               FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
3648             }
3649           }
3650           /* FPSCR[FR] <- undefined */
3651           FPSCR_SET_FI(1);
3652           FPSCR_SET_XX(1);
3653           goto Done;
3654         Enabled_Exponent_Overflow:
3655           sign = EXTRACTED64(*frB, 0, 0);
3656           exp = EXTRACTED64(*frB, 1, 11) - 1023;
3657           frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
3658           Round_Single(processor, sign, &exp, &frac_grx);
3659           FPSCR_SET_XX(FPSCR & fpscr_fi);
3660           Enabled_Overflow:
3661             FPSCR_SET_OX(1);
3662             exp = exp - 192;
3663             *frT = (INSERTED64(sign, 0, 0)
3664                     | INSERTED64(exp + 1023, 1, 11)
3665                     | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
3666             if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
3667             if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
3668           goto Done;
3669         Zero_Operand:
3670           *frT = *frB;
3671           if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
3672           if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
3673           FPSCR_SET_FR(0);
3674           FPSCR_SET_FI(0);
3675           goto Done;
3676         Infinity_Operand:
3677           *frT = *frB;
3678           if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
3679           if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
3680           FPSCR_SET_FR(0);
3681           FPSCR_SET_FI(0);
3682           goto Done;
3683         QNaN_Operand:
3684           *frT = INSERTED64(EXTRACTED64(*frB, 0, 34), 0, 34);
3685           FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
3686           FPSCR_SET_FR(0);
3687           FPSCR_SET_FI(0);
3688           goto Done;
3689         SNaN_Operand:
3690           FPSCR_OR_VX(fpscr_vxsnan);
3691           if ((FPSCR & fpscr_ve) == 0) {
3692             *frT = (MASKED64(*frB, 0, 11)
3693                     | BIT64(12)
3694                     | MASKED64(*frB, 13, 34));
3695             FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
3696           }
3697           FPSCR_SET_FR(0);
3698           FPSCR_SET_FI(0);
3699           goto Done;
3700         Normal_Operand:
3701           sign = EXTRACTED64(*frB, 0, 0);
3702           exp = EXTRACTED64(*frB, 1, 11) - 1023;
3703           frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
3704           Round_Single(processor, sign, &exp, &frac_grx);
3705           FPSCR_SET_XX(FPSCR & fpscr_fi);
3706           if (exp > 127 && (FPSCR & fpscr_oe) == 0) goto Disabled_Exponent_Overflow;
3707           if (exp > 127 && (FPSCR & fpscr_oe) != 0) goto Enabled_Overflow;
3708           *frT = (INSERTED64(sign, 0, 0)
3709                   | INSERTED64(exp + 1023, 1, 11)
3710                   | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
3711           if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
3712           if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
3713           goto Done;
3714         Done:
3715
3716 0.63,6.FRT,11./,16.FRB,21.814,31.Rc:X:64,f::Floating Convert To Integer Doubleword
3717
3718 0.63,6.FRT,11./,16.FRB,21.815,31.Rc:X:64,f::Floating Convert To Integer Doubleword with round towards Zero
3719
3720 0.63,6.FRT,11./,16.FRB,21.14,31.Rc:X:f::Floating Convert To Integer Word
3721
3722 0.63,6.FRT,11./,16.FRB,21.15,31.Rc:X:f:fctiwz:Floating Convert To Integer Word with round towards Zero
3723 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3724 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3725 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3726 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3727         FPSCR_BEGIN;
3728         convert_to_integer(processor, cia,
3729                            frT, *frB,
3730                            fpscr_rn_round_towards_zero, 32);
3731         FPSCR_END(Rc);
3732
3733 0.63,6.FRT,11./,16.FRB,21.846,31.Rc:X:64,f::Floating Convert from Integer Doubleword
3734         int sign = EXTRACTED64(*frB, 0, 0);
3735         int exp = 63;
3736         unsigned64 frac = *frB;
3737         if (frac == 0) goto Zero_Operand;
3738         if (sign == 1) frac = ~frac + 1;
3739         while (EXTRACTED64(frac, 0, 0) == 0) {
3740           /*??? do the loop 0 times if (FRB) = max negative integer */
3741           frac = INSERTED64(EXTRACTED64(frac, 1, 63), 0, 62);
3742           exp = exp - 1;
3743         }
3744         Round_Float(processor, sign, &exp, &frac, FPSCR & fpscr_rn);
3745         if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
3746         if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
3747         *frT = (INSERTED64(sign, 0, 0)
3748                 | INSERTED64(exp + 1023, 1, 11)
3749                 | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
3750         goto Done;
3751         /**/
3752         Zero_Operand:
3753           FPSCR_SET_FR(0);
3754           FPSCR_SET_FI(0);
3755           FPSCR_SET_FPRF(fpscr_rf_pos_zero);
3756           *frT = 0;
3757           goto Done;
3758         /**/
3759         Done:
3760
3761 #
3762 # I.4.6.7 Floating-Point Compare Instructions
3763 #
3764
3765 0.63,6.BF,9./,11.FRA,16.FRB,21.0,31./:X:f:fcmpu:Floating Compare Unordered
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         unsigned c;
3772         if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
3773           c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
3774         else if (is_less_than(frA, frB))
3775           c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
3776         else if (is_greater_than(frA, frB))
3777           c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
3778         else
3779           c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
3780         FPSCR_SET_FPCC(c);
3781         CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
3782         if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0))
3783           FPSCR_OR_VX(fpscr_vxsnan);
3784         FPSCR_END(0);
3785
3786 0.63,6.BF,9./,11.FRA,16.FRB,21.32,31./:X:f:fcmpo:Floating Compare Ordered
3787 *601: PPC_UNIT_FPU,   PPC_UNIT_FPU,   4,  4,  0
3788 *603: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3789 *603e:PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3790 *604: PPC_UNIT_FPU,   PPC_UNIT_FPU,   1,  3,  0
3791         FPSCR_BEGIN;
3792         unsigned c;
3793         if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
3794           c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
3795         else if (is_less_than(frA, frB))
3796           c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
3797         else if (is_greater_than(frA, frB))
3798           c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
3799         else
3800           c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
3801         FPSCR_SET_FPCC(c);
3802         CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
3803         if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0)) {
3804           FPSCR_OR_VX(fpscr_vxsnan);
3805           if ((FPSCR & fpscr_ve) == 0)
3806             FPSCR_OR_VX(fpscr_vxvc);
3807         }
3808         else if (is_QNaN(*frA, 0) || is_QNaN(*frB, 0)) {
3809           FPSCR_OR_VX(fpscr_vxvc);
3810         }
3811         FPSCR_END(0);
3812
3813
3814 #
3815 # I.4.6.8 Floating-Point Status and Control Register Instructions
3816 #
3817
3818 0.63,6.FRT,11./,16./,21.583,31.Rc:X:f::Move From FPSCR
3819
3820 0.63,6.BF,9./,11.BFA,14./,16./,21.64,31./:X:f::Move to Condition Register from FPSCR
3821
3822 0.64,6.BF,9./,11./,16.U,20./,21.134,31.Rc:X:f::Move To FPSCR Field Immediate
3823
3824 0.63,6./,7.FLM,15./,16.FRB,21.711,31.Rc:XFL:f::Move To FPSCR Fields
3825
3826 0.63,6.BT,11./,16./,21.70,31.Rc:X:f::Move To FPSCR Bit 0
3827
3828 0.63,6.BT,11./,16./,21.38,31.Rc:X:f::Move To FPSCR Bit 1
3829
3830
3831 #
3832 # I.A.1.1 Floating-Point Store Instruction
3833 #
3834 0.31,6.FRS,11.RA,16.RB,21.983,31./:X:f::Store Floating-Point as Integer Word Indexed
3835
3836 #
3837 # I.A.1.2 Floating-Point Arithmetic Instructions
3838 #
3839
3840 0.63,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f::Floating Square Root
3841
3842 0.59,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f::Floating Square Root Single
3843
3844 0.59,6.FRT,11./,16.FRB,21./,26.24,31.Rc:A:f::Floating Reciprocal Estimate Single
3845
3846 0.63,6.FRT,11./,16.FRB,21./,26.26,31.Rc:A:f::Floating Reciprocal Square Root Estimate
3847
3848 #
3849 # I.A.1.3 Floating-Point Select Instruction
3850 #
3851
3852 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.23,31.Rc:A:f::Floating Select
3853
3854
3855 #
3856 # II.3.2 Cache Management Instructions
3857 #
3858
3859 0.31,6./,11.RA,16.RB,21.982,31./:X::icbi:Instruction Cache Block Invalidate
3860 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3861 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3862 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3863 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  1,  0
3864         /* blindly flush all instruction cache entries */
3865         #if WITH_IDECODE_CACHE_SIZE
3866         cpu_flush_icache(processor);
3867         #endif
3868
3869 0.19,6./,11./,16./,21.150,31./:XL::isync:Instruction Synchronize
3870 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3871 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3872 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3873 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  1,  0
3874         cpu_synchronize_context(processor);
3875
3876
3877 #
3878 # II.3.2.2 Data Cache Instructions
3879 #
3880
3881 0.31,6./,11.RA,16.RB,21.278,31./:X:::Data Cache Block Touch
3882 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3883 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   2,  2,  0
3884 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   2,  2,  0
3885 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  1,  0
3886         TRACE(trace_tbd,("Data Cache Block Touch\n"));
3887
3888 0.31,6./,11.RA,16.RB,21.246,31./:X:::Data Cache Block Touch for Store
3889 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3890 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   2,  2,  0
3891 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   2,  2,  0
3892 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3893         TRACE(trace_tbd,("Data Cache Block Touch for Store\n"));
3894
3895 0.31,6./,11.RA,16.RB,21.1014,31./:X:::Data Cache Block set to Zero
3896 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3897 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   10, 10, 0
3898 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   10, 10, 0
3899 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
3900         TRACE(trace_tbd,("Data Cache Block set to Zero\n"));
3901
3902 0.31,6./,11.RA,16.RB,21.54,31./:X:::Data Cache Block Store
3903 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3904 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   5,  5,  0
3905 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   5,  5,  0
3906 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  1,  0
3907         TRACE(trace_tbd,("Data Cache Block Store\n"));
3908
3909 0.31,6./,11.RA,16.RB,21.86,31./:X:::Data Cache Block Flush
3910 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3911 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   5,  5,  0
3912 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   5,  5,  0
3913 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  1,  0
3914         TRACE(trace_tbd,("Data Cache Block Flush\n"));
3915
3916 #
3917 # II.3.3 Enforce In-order Execution of I/O Instruction
3918 #
3919
3920 0.31,6./,11./,16./,21.854,31./:X::eieio:Enforce In-order Execution of I/O
3921         /* Since this model has no instruction overlap
3922            this instruction need do nothing */
3923
3924 #
3925 # II.4.1 Time Base Instructions
3926 #
3927
3928 0.31,6.RT,11.tbr,21.371,31./:XFX::mftb:Move From Time Base
3929 *603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
3930 *603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
3931 *604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  3,  3,  0
3932         int n = (tbr{5:9} << 5) | tbr{0:4};
3933         if (n == 268) {
3934           if (is_64bit_implementation) *rT = TB;
3935           else                         *rT = EXTRACTED64(TB, 32, 63);
3936         }
3937         else if (n == 269) {
3938           if (is_64bit_implementation) *rT = EXTRACTED64(TB, 0, 31);
3939           else                         *rT = EXTRACTED64(TB, 0, 31);
3940         }
3941         else
3942           program_interrupt(processor, cia,
3943                             illegal_instruction_program_interrupt);
3944
3945
3946 #
3947 # III.2.3.1 System Linkage Instructions
3948 #
3949
3950 0.19,6./,11./,16./,21.50,31./:XL::rfi:Return From Interrupt
3951 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3952 *603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   3,  3,  0
3953 *603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   3,  3,  0
3954 *604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  3,  3,  0
3955         if (IS_PROBLEM_STATE(processor)) {
3956           program_interrupt(processor, cia,
3957                             privileged_instruction_program_interrupt);
3958         }
3959         else {
3960           MSR = (MASKED(SRR1, 0, 32)
3961                  | MASKED(SRR1, 37, 41)
3962                  | MASKED(SRR1, 48, 63));
3963           NIA = MASKED(SRR0, 0, 61);
3964           cpu_synchronize_context(processor);
3965         }
3966
3967 #
3968 # III.3.4.1 Move to/from System Register Instructions
3969 #
3970
3971 #0.31,6.RS,11.spr,21.467,31./:XFX:::Move To Special Purpose Register
3972 #0.31,6.RT,11.spr,21.339,31./:XFX:::Move From Special Purpose Register
3973 0.31,6.RS,11./,16./,21.146,31./:X:::Move To Machine State Register
3974 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3975 *603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   2,  2,  0
3976 *603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   2,  2,  0
3977 *604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  1,  1,  0
3978         if (IS_PROBLEM_STATE(processor))
3979           program_interrupt(processor, cia,
3980                             privileged_instruction_program_interrupt);
3981         else
3982           MSR = *rS;
3983
3984 0.31,6.RT,11./,16./,21.83,31./:X:::Move From Machine State Register
3985 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
3986 *603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
3987 *603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   1,  1,  0
3988 *604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  3,  3,  0
3989         if (IS_PROBLEM_STATE(processor))
3990           program_interrupt(processor, cia,
3991                             privileged_instruction_program_interrupt);
3992         else
3993           *rT = MSR;
3994
3995
3996 #
3997 # III.4.11.1 Cache Management Instructions
3998 #
3999
4000 0.31,6./,11.RA,16.RB,21.470,31./:X::dcbi:Data Cache Block Invalidate
4001 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4002 *603: PPC_UNIT_LSU,   PPC_UNIT_LSU,   2,  2,  0
4003 *603e:PPC_UNIT_LSU,   PPC_UNIT_LSU,   2,  2,  0
4004 *604: PPC_UNIT_LSU,   PPC_UNIT_LSU,   1,  3,  0
4005         if (IS_PROBLEM_STATE(processor))
4006           program_interrupt(processor, cia,
4007                             privileged_instruction_program_interrupt);
4008         else
4009           TRACE(trace_tbd,("Data Cache Block Invalidate\n"));
4010
4011 #
4012 # III.4.11.2 Segment Register Manipulation Instructions
4013 #
4014
4015 0.31,6.RS,11./,12.SR,16./,21.210,31./:X:32:mtsr %SR,%RS:Move To Segment Register
4016 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4017 *603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   2,  2,  0
4018 *603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   2,  2,  0
4019 *604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  1,  1,  0
4020         if (IS_PROBLEM_STATE(processor))
4021           program_interrupt(processor, cia,
4022                             privileged_instruction_program_interrupt);
4023         else
4024           SEGREG(SR) = *rS;
4025
4026 0.31,6.RS,11./,16.RB,21.242,31./:X:32:mtsrin %RS,%RB:Move To Segment Register Indirect
4027 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    1,  1,  0
4028 *603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   2,  2,  0
4029 *603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   2,  2,  0
4030 *604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  1,  1,  0
4031         if (IS_PROBLEM_STATE(processor))
4032           program_interrupt(processor, cia,
4033                             privileged_instruction_program_interrupt);
4034         else
4035           SEGREG(EXTRACTED32(*rB, 0, 3)) = *rS;
4036
4037 0.31,6.RT,11./,12.SR,16./,21.595,31./:X:32:mfsr %RT,%RS:Move From Segment Register
4038 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    2,  2,  0
4039 *603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   3,  3,  0
4040 *603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   3,  3,  0
4041 *604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  1,  1,  0
4042         if (IS_PROBLEM_STATE(processor))
4043           program_interrupt(processor, cia,
4044                             privileged_instruction_program_interrupt);
4045         else
4046           *rT = SEGREG(SR);
4047
4048 0.31,6.RT,11./,16.RB,21.659,31./:X:32:mfsrin %RT,%RB:Move From Segment Register Indirect
4049 *601: PPC_UNIT_IU,    PPC_UNIT_IU,    2,  2,  0
4050 *603: PPC_UNIT_SRU,   PPC_UNIT_SRU,   3,  3,  0
4051 *603e:PPC_UNIT_SRU,   PPC_UNIT_SRU,   3,  3,  0
4052 *604: PPC_UNIT_MCIU,  PPC_UNIT_MCIU,  1,  1,  0
4053         if (IS_PROBLEM_STATE(processor))
4054           program_interrupt(processor, cia,
4055                             privileged_instruction_program_interrupt);
4056         else
4057           *rT = SEGREG(EXTRACTED32(*rB, 0, 3));
4058
4059
4060 #
4061 # III.4.11.3 Lookaside Buffer Management Instructions (Optional)
4062 #
4063
4064 0.31,6./,11./,16.RB,21.434,31./:X:64::SLB Invalidate Entry
4065
4066 0.31,6./,11./,16./,21.498,31./:X:64::SLB Invalidate All
4067
4068 0.31,6./,11./,16.RB,21.306,31./:X:::TLB Invalidate Entry
4069
4070 0.31,6./,11./,16./,21.370,31./:X:::TLB Invalidate All
4071
4072 0.31,6./,11./,16./,21.566,31./:X:::TLB Sychronize
4073
4074
4075 #
4076 # III.A.1.2 External Access Instructions
4077 #
4078
4079 0.31,6.RT,11.RA,16.RB,21.310,31./:X:earwax::External Control In Word Indexed
4080
4081 0.31,6.RS,11.RA,16.RB,21.438,31./:X:earwax::External Control Out Word Indexed