2 # This file is part of the program psim.
4 # Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
8 # The pseudo-code that appears below, translated into C, was copied
9 # by Andrew Cagney of Moss Vale, Australia.
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.
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.
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.
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.
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.
38 ::model:604:ppc604: PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0
39 ::model:603e:ppc603e:PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0
40 ::model:603:ppc603: PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0
41 ::model:601:ppc601: PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0
45 #define PPC_INSN_INT(OUT_MASK, IN_MASK, RC) \
47 if (CURRENT_MODEL_ISSUE > 0) { \
49 ppc_insn_int(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK); \
51 ppc_insn_int_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, 1 << 0); \
55 #define PPC_INSN_INT_CR(OUT_MASK, IN_MASK, CR_MASK) \
57 if (CURRENT_MODEL_ISSUE > 0) \
58 ppc_insn_int_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, CR_MASK); \
61 #define PPC_INSN_CR(OUT_MASK, IN_MASK) \
63 if (CURRENT_MODEL_ISSUE > 0) \
64 ppc_insn_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK); \
67 #define PPC_INSN_FLOAT(OUT_MASK, IN_MASK, RC) \
69 if (CURRENT_MODEL_ISSUE > 0) { \
71 ppc_insn_float(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK); \
73 ppc_insn_float_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, 1 << 0); \
77 #define PPC_INSN_FLOAT_CR(OUT_MASK, IN_MASK, CR_MASK) \
79 if (CURRENT_MODEL_ISSUE > 0) \
80 ppc_insn_float_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, CR_MASK); \
83 #define PPC_INSN_INT_FLOAT(OUT_INT_MASK, OUT_FP_MASK, IN_INT_MASK, IN_FP_MASK) \
85 if (CURRENT_MODEL_ISSUE > 0) \
86 ppc_insn_int_float(MY_INDEX, cpu_model(processor), OUT_INT_MASK, OUT_FP_MASK, IN_INT_MASK, IN_FP_MASK); \
89 #define PPC_INSN_FROM_SPR(INT_MASK, SPR) \
91 if (CURRENT_MODEL_ISSUE > 0) \
92 ppc_insn_from_spr(MY_INDEX, cpu_model(processor), INT_MASK, SPR); \
95 #define PPC_INSN_TO_SPR(INT_MASK, SPR) \
97 if (CURRENT_MODEL_ISSUE > 0) \
98 ppc_insn_to_spr(MY_INDEX, cpu_model(processor), INT_MASK, SPR); \
101 #define PPC_INSN_MFCR(INT_MASK) \
103 if (CURRENT_MODEL_ISSUE > 0) \
104 ppc_insn_mfcr(MY_INDEX, cpu_model(processor), INT_MASK); \
107 #define PPC_INSN_MTCR(INT_MASK, FXM) \
109 if (CURRENT_MODEL_ISSUE > 0) \
110 ppc_insn_mtcr(MY_INDEX, cpu_model(processor), INT_MASK, FXM); \
114 typedef enum _ppc_function_unit {
115 PPC_UNIT_BAD, /* unknown function unit */
116 PPC_UNIT_IU, /* integer unit (601/603 style) */
117 PPC_UNIT_SRU, /* system register unit (601/603 style) */
118 PPC_UNIT_SCIU1, /* 1st single cycle integer unit (604 style) */
119 PPC_UNIT_SCIU2, /* 2nd single cycle integer unit (604 style) */
120 PPC_UNIT_MCIU, /* multiple cycle integer unit (604 style) */
121 PPC_UNIT_FPU, /* floating point unit */
122 PPC_UNIT_LSU, /* load/store unit */
123 PPC_UNIT_BPU, /* branch unit */
124 nr_ppc_function_units
127 /* Structure to hold timing information on a per instruction basis */
129 ppc_function_unit first_unit; /* first functional unit this insn could use */
130 ppc_function_unit second_unit; /* second functional unit this insn could use */
131 signed16 issue; /* # cycles before function unit can process other insns */
132 signed16 done; /* # cycles before insn is done */
133 unsigned32 flags; /* any flags that are needed */
136 /* Register mappings in status masks */
137 #define PPC_CR_REG 0 /* start of CR0 .. CR7 */
138 #define PPC_FPSCR_REG (PPC_CR_REG + 8) /* start of fpscr register */
140 #define PPC_NO_SPR (-1) /* flag for no SPR register */
142 /* Return if 1 bit set */
143 #define PPC_ONE_BIT_SET_P(x) (((x) & ((x)-1)) == 0)
145 /* Structure for each functional unit that is busy */
146 typedef struct _model_busy model_busy;
148 model_busy *next; /* next function unit */
149 ppc_function_unit unit; /* function unit name */
150 unsigned32 int_busy; /* int registers that are busy */
151 unsigned32 fp_busy; /* floating point registers that are busy */
152 unsigned32 cr_fpscr_busy; /* CR/FPSCR registers that are busy */
153 signed16 spr_busy; /* SPR register that is busy or PPC_NO_SPR */
154 signed16 issue; /* # of cycles until unit can accept another insn */
155 signed16 done; /* # of cycles until insn is done */
156 signed16 nr_writebacks; /* # of registers this unit writes back */
159 /* Structure to hold the current state information for the simulated CPU model */
161 cpu *processor; /* point back to processor */
162 const char *name; /* model name */
163 const model_time *timing; /* timing information */
164 model_busy busy_head; /* dummy entry to head list of busy function units */
165 model_busy *busy_tail; /* tail of list of busy function units */
166 model_busy *free_list; /* list of model_busy structs not in use */
167 count_type nr_cycles; /* # cycles */
168 count_type nr_branches; /* # branches */
169 count_type nr_branches_fallthrough; /* # conditional branches that fell through */
170 count_type nr_branch_predict_trues; /* # branches predicted correctly */
171 count_type nr_branch_predict_falses; /* # branches predicted incorrectly */
172 count_type nr_branch_conditional[32]; /* # of each type of bc */
173 count_type nr_mtcrf_crs[9]; /* # of CR's moved in a mtcrf instruction */
174 count_type nr_stalls_data; /* # of stalls for data */
175 count_type nr_stalls_unit; /* # of stalls waiting for a function unit */
176 count_type nr_stalls_serialize; /* # of stalls waiting for things to quiet down */
177 count_type nr_stalls_writeback; /* # of stalls waiting for a writeback slot */
178 count_type nr_units[nr_ppc_function_units]; /* function unit counts */
179 int max_nr_writebacks; /* max # of writeback slots available */
180 unsigned32 int_busy; /* int registers that are busy */
181 unsigned32 fp_busy; /* floating point registers that are busy */
182 unsigned32 cr_fpscr_busy; /* CR/FPSCR registers that are busy */
183 unsigned8 spr_busy[nr_of_sprs]; /* SPR registers that are busy */
184 unsigned8 busy[nr_ppc_function_units]; /* whether a function is busy or not */
187 static const char *const ppc_function_unit_name[ (int)nr_ppc_function_units ] = {
188 "unknown functional unit instruction",
189 "integer functional unit instruction",
190 "system register functional unit instruction",
191 "1st single cycle integer functional unit instruction",
192 "2nd single cycle integer functional unit instruction",
193 "multiple cycle integer functional unit instruction",
194 "floating point functional unit instruction",
195 "load/store functional unit instruction",
196 "branch functional unit instruction",
199 static const char *const ppc_branch_conditional_name[32] = {
200 "branch if --CTR != 0 and condition is FALSE", /* 0000y */
201 "branch if --CTR != 0 and condition is FALSE, reverse branch likely",
202 "branch if --CTR == 0 and condition is FALSE", /* 0001y */
203 "branch if --CTR == 0 and condition is FALSE, reverse branch likely",
204 "branch if the condition is FALSE", /* 001zy */
205 "branch if the condition is FALSE, reverse branch likely",
206 "branch if the condition is FALSE (ignored bit 1 set to 1)", /* 001zy */
207 "branch if the condition is FALSE, reverse branch likely (ignored bit 4 set to 1)",
208 "branch if --CTR != 0 and condition is TRUE", /* 0100y */
209 "branch if --CTR != 0 and condition is TRUE, reverse branch likely",
210 "branch if --CTR == 0 and condition is TRUE", /* 0101y */
211 "branch if --CTR == 0 and condition is TRUE, reverse branch likely",
212 "branch if the condition is TRUE", /* 011zy */
213 "branch if the condition is TRUE, reverse branch likely",
214 "branch if the condition is TRUE (ignored bit 1 set to 1)", /* 011zy */
215 "branch if the condition is TRUE, reverse branch likely (ignored bit 4 set to 1)",
216 "branch if --CTR != 0", /* 1z00y */
217 "branch if --CTR != 0, reverse branch likely",
218 "branch if --CTR == 0", /* 1z01y */
219 "branch if --CTR == 0, reverse branch likely",
220 "branch always", /* 1z1zz */
221 "branch always (ignored bit 5 set to 1)",
222 "branch always (ignored bit 4 set to 1)", /* 1z1zz */
223 "branch always (ignored bits 4,5 set to 1)",
224 "branch if --CTR != 0 (ignored bit 1 set to 1)", /* 1z00y */
225 "branch if --CTR != 0, reverse branch likely (ignored bit 1 set to 1)",
226 "branch if --CTR == 0 (ignored bit 1 set to 1)", /* 1z01y */
227 "branch if --CTR == 0, reverse branch likely (ignored bit 1 set to 1)",
228 "branch always (ignored bit 1 set to 1)", /* 1z1zz */
229 "branch always (ignored bits 1,5 set to 1)",
230 "branch always (ignored bits 1,4 set to 1)", /* 1z1zz */
231 "branch always (ignored bits 1,4,5 set to 1)",
234 static const char *const ppc_nr_mtcrf_crs[9] = {
235 "mtcrf moving 0 CRs",
237 "mtcrf moving 2 CRs",
238 "mtcrf moving 3 CRs",
239 "mtcrf moving 4 CRs",
240 "mtcrf moving 5 CRs",
241 "mtcrf moving 6 CRs",
242 "mtcrf moving 7 CRs",
243 "mtcrf moving all CRs",
246 # Trace releasing resources
247 void::model-static::model_trace_release:model_data *model_ptr, model_busy *busy
249 TRACE(trace_model,("done, %s, %d writeback%s\n", ppc_function_unit_name[busy->unit],
250 busy->nr_writebacks, busy->nr_writebacks == 1 ? "" : "s"));
251 if (busy->int_busy) {
252 for(i = 0; i < 32; i++) {
253 if (((1 << i) & busy->int_busy) != 0) {
254 TRACE(trace_model, ("Register r%d is now available.\n", i));
259 for(i = 0; i < 32; i++) {
260 if (((1 << i) & busy->fp_busy) != 0) {
261 TRACE(trace_model, ("Register f%d is now available.\n", i));
265 if (busy->cr_fpscr_busy) {
266 for(i = 0; i < 8; i++) {
267 if (((1 << i) & busy->cr_fpscr_busy) != 0) {
268 TRACE(trace_model, ("Register cr%d is now available.\n", i));
271 if (busy->cr_fpscr_busy & 0x100)
272 TRACE(trace_model, ("Register fpscr is now available.\n"));
274 if (busy->spr_busy != PPC_NO_SPR)
275 TRACE(trace_model, ("Register %s is now available.\n", spr_name(busy->spr_busy)));
277 # Trace making registers busy
278 void::model-static::model_trace_make_busy:model_data *model_ptr, unsigned32 int_mask, unsigned32 fp_mask, unsigned32 cr_mask
281 for(i = 0; i < 32; i++) {
282 if (((1 << i) & int_mask) != 0) {
283 TRACE(trace_model, ("Register r%d is now busy.\n", i));
288 for(i = 0; i < 32; i++) {
289 if (((1 << i) & fp_mask) != 0) {
290 TRACE(trace_model, ("Register f%d is now busy.\n", i));
295 for(i = 0; i < 8; i++) {
296 if (((1 << i) & cr_mask) != 0) {
297 TRACE(trace_model, ("Register cr%d is now busy.\n", i));
302 # Trace waiting for registers to become available
303 void::model-static::model_trace_busy_p:model_data *model_ptr, unsigned32 int_busy, unsigned32 fp_busy, unsigned32 cr_or_fpscr_busy, int spr_busy
306 int_busy &= model_ptr->int_busy;
307 for(i = 0; i < 32; i++) {
308 if (((1 << i) & int_busy) != 0) {
309 TRACE(trace_model, ("Waiting for register r%d.\n", i));
314 fp_busy &= model_ptr->fp_busy;
315 for(i = 0; i < 32; i++) {
316 if (((1 << i) & fp_busy) != 0) {
317 TRACE(trace_model, ("Waiting for register f%d.\n", i));
321 if (cr_or_fpscr_busy) {
322 cr_or_fpscr_busy &= model_ptr->cr_fpscr_busy;
323 for(i = 0; i < 8; i++) {
324 if (((1 << i) & cr_or_fpscr_busy) != 0) {
325 TRACE(trace_model, ("Waiting for register cr%d.\n", i));
328 if (cr_or_fpscr_busy & 0x100)
329 TRACE(trace_model, ("Waiting for register fpscr.\n"));
331 if (spr_busy != PPC_NO_SPR && model_ptr->spr_busy[spr_busy])
332 TRACE(trace_model, ("Waiting for register %s.\n", spr_name(spr_busy)));
334 # Advance state to next cycle, releasing any registers allocated
335 void::model-internal::model_new_cycle:model_data *model_ptr
336 model_busy *cur_busy = model_ptr->busy_head.next;
337 model_busy *free_list = model_ptr->free_list;
338 model_busy *busy_tail = &model_ptr->busy_head;
339 int nr_writebacks = model_ptr->max_nr_writebacks;
342 model_ptr->nr_cycles++;
343 TRACE(trace_model,("New cycle %lu\n", (unsigned long)model_ptr->nr_cycles));
344 for ( ; cur_busy; cur_busy = next) {
345 next = cur_busy->next;
346 if (--cur_busy->done <= 0) { /* function unit done, release registers if we have writeback slots */
347 nr_writebacks -= cur_busy->nr_writebacks;
348 if (nr_writebacks >= 0) {
349 model_ptr->int_busy &= ~cur_busy->int_busy;
350 model_ptr->fp_busy &= ~cur_busy->fp_busy;
351 model_ptr->cr_fpscr_busy &= ~cur_busy->cr_fpscr_busy;
352 if (cur_busy->spr_busy != PPC_NO_SPR)
353 model_ptr->spr_busy[cur_busy->spr_busy] = 0;
355 if (WITH_TRACE && ppc_trace[trace_model])
356 model_trace_release(model_ptr, cur_busy);
358 model_ptr->busy[cur_busy->unit] = 0;
359 cur_busy->next = free_list;
360 free_list = cur_busy;
362 else { /* writeback slots not available */
363 TRACE(trace_model,("%d writeback slot%s not available for %s\n",
364 cur_busy->nr_writebacks,
365 cur_busy->nr_writebacks == 1 ? " is" : "s are",
366 ppc_function_unit_name[cur_busy->unit]));
367 cur_busy->done++; /* undo -- above */
368 model_ptr->nr_stalls_writeback++;
369 busy_tail->next = cur_busy;
370 busy_tail = cur_busy;
373 else if (--cur_busy->issue <= 0) { /* function unit pipelined, allow new use */
374 TRACE(trace_model,("pipeline, %s ready for next client\n", ppc_function_unit_name[cur_busy->unit]));
375 model_ptr->busy[cur_busy->unit] = 0;
376 busy_tail->next = cur_busy;
377 busy_tail = cur_busy;
380 TRACE(trace_model,("%s still working, issue = %d, done = %d\n",
381 ppc_function_unit_name[cur_busy->unit],
384 busy_tail->next = cur_busy;
385 busy_tail = cur_busy;
389 busy_tail->next = (model_busy *)0;
390 model_ptr->busy_tail = busy_tail;
391 model_ptr->free_list = free_list;
393 # Mark a function unit as busy, return the busy structure
394 model_busy *::model-internal::model_make_busy:model_data *model_ptr, ppc_function_unit unit, int issue, int done
397 TRACE(trace_model,("unit = %s, issue = %d, done = %d\n", ppc_function_unit_name[unit], issue, done));
399 if (!model_ptr->free_list) {
400 busy = ZALLOC(model_busy);
403 busy = model_ptr->free_list;
404 model_ptr->free_list = busy->next;
405 busy->next = (model_busy *)0;
408 busy->cr_fpscr_busy = 0;
409 busy->nr_writebacks = 0;
415 busy->spr_busy = PPC_NO_SPR;
416 model_ptr->busy_tail->next = busy;
417 model_ptr->busy_tail = busy;
418 model_ptr->busy[unit] = 1;
419 model_ptr->nr_units[unit]++;
422 # Wait until a function unit is non-busy, and then allocate a busy pointer & return the pointer
423 model_busy *::model-internal::model_wait_for_unit:itable_index index, model_data *const model_ptr, const model_time *const time_ptr
424 ppc_function_unit first_unit = time_ptr->first_unit;
425 ppc_function_unit second_unit = time_ptr->second_unit;
426 int stall_increment = 0;
429 if (!model_ptr->busy[first_unit])
430 return model_make_busy(model_ptr, first_unit,
431 model_ptr->timing[index].issue,
432 model_ptr->timing[index].done);
434 if (!model_ptr->busy[second_unit])
435 return model_make_busy(model_ptr, second_unit,
436 model_ptr->timing[index].issue,
437 model_ptr->timing[index].done);
439 TRACE(trace_model,("all function units are busy for %s\n", itable[index].name));
440 model_ptr->nr_stalls_unit += stall_increment; /* don't count first stall */
442 model_new_cycle(model_ptr);
445 # Serialize the processor, waiting for all instructions to drain out before adding an instruction.
446 void::model-function::model_serialize:itable_index index, model_data *model_ptr
447 while (model_ptr->busy_head.next) {
448 TRACE(trace_model,("waiting for pipeline to empty\n"));
449 model_ptr->nr_stalls_serialize++;
450 model_new_cycle(model_ptr);
452 (void) model_make_busy(model_ptr,
453 model_ptr->timing[index].first_unit,
454 model_ptr->timing[index].issue,
455 model_ptr->timing[index].done);
457 # Wait for a CR to become unbusy
458 void::model-function::model_wait_for_cr:model_data *model_ptr, unsigned CRBIT
462 for (u = 0xc0000000; (u != 0) && (CRBIT & u) == 0; u >>= 4 )
465 cr_mask = (1 << cr_var);
466 while ((model_ptr->cr_fpscr_busy & cr_mask) != 0) {
467 TRACE(trace_model,("waiting for CR %d\n", cr_var));
468 model_ptr->nr_stalls_data++;
469 model_new_cycle(model_ptr);
472 # Schedule an instruction that takes integer input registers and produces output registers
473 void::model-function::ppc_insn_int:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask
474 const unsigned32 int_mask = out_mask | in_mask;
475 model_busy *busy_ptr;
477 if ((model_ptr->int_busy & int_mask) != 0) {
478 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
480 while ((model_ptr->int_busy & int_mask) != 0) {
481 if (WITH_TRACE && ppc_trace[trace_model])
482 model_trace_busy_p(model_ptr, int_mask, 0, 0, PPC_NO_SPR);
484 model_ptr->nr_stalls_data++;
485 model_new_cycle(model_ptr);
489 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
490 model_ptr->int_busy |= out_mask;
491 busy_ptr->int_busy |= out_mask;
493 busy_ptr->nr_writebacks = (PPC_ONE_BIT_SET_P(out_mask)) ? 1 : 2;
495 if (WITH_TRACE && ppc_trace[trace_model])
496 model_trace_make_busy(model_ptr, out_mask, 0, 0);
498 # Schedule an instruction that takes integer input registers and produces output registers & sets a CR register
499 void::model-function::ppc_insn_int_cr:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask, const unsigned32 cr_mask
500 const unsigned32 int_mask = out_mask | in_mask;
501 model_busy *busy_ptr;
503 if ((model_ptr->int_busy & int_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
504 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
506 while ((model_ptr->int_busy & int_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
507 if (WITH_TRACE && ppc_trace[trace_model])
508 model_trace_busy_p(model_ptr, int_mask, 0, cr_mask, PPC_NO_SPR);
510 model_ptr->nr_stalls_data++;
511 model_new_cycle(model_ptr);
515 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
516 model_ptr->int_busy |= out_mask;
517 busy_ptr->int_busy |= out_mask;
518 model_ptr->cr_fpscr_busy |= cr_mask;
519 busy_ptr->cr_fpscr_busy |= cr_mask;
521 busy_ptr->nr_writebacks = (PPC_ONE_BIT_SET_P(out_mask)) ? 1 : 2;
524 busy_ptr->nr_writebacks++;
526 if (WITH_TRACE && ppc_trace[trace_model])
527 model_trace_make_busy(model_ptr, out_mask, 0, cr_mask);
530 # Schedule an instruction that takes CR input registers and produces output CR registers
531 void::model-function::ppc_insn_cr:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask
532 const unsigned32 cr_mask = out_mask | in_mask;
533 model_busy *busy_ptr;
535 if ((model_ptr->cr_fpscr_busy & cr_mask) != 0) {
536 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
538 while ((model_ptr->cr_fpscr_busy & cr_mask) != 0) {
539 if (WITH_TRACE && ppc_trace[trace_model])
540 model_trace_busy_p(model_ptr, 0, 0, cr_mask, PPC_NO_SPR);
542 model_ptr->nr_stalls_data++;
543 model_new_cycle(model_ptr);
547 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
548 model_ptr->cr_fpscr_busy |= out_mask;
549 busy_ptr->cr_fpscr_busy |= out_mask;
551 busy_ptr->nr_writebacks = 1;
553 if (WITH_TRACE && ppc_trace[trace_model])
554 model_trace_make_busy(model_ptr, 0, 0, out_mask);
557 # Schedule an instruction that takes floating point input registers and produces an output fp register
558 void::model-function::ppc_insn_float:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask
559 const unsigned32 fp_mask = out_mask | in_mask;
560 model_busy *busy_ptr;
562 if ((model_ptr->fp_busy & fp_mask) != 0) {
563 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
565 while ((model_ptr->fp_busy & fp_mask) != 0) {
566 if (WITH_TRACE && ppc_trace[trace_model])
567 model_trace_busy_p(model_ptr, 0, fp_mask, 0, PPC_NO_SPR);
569 model_ptr->nr_stalls_data++;
570 model_new_cycle(model_ptr);
574 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
575 model_ptr->fp_busy |= out_mask;
576 busy_ptr->fp_busy |= out_mask;
577 busy_ptr->nr_writebacks = 1;
578 if (WITH_TRACE && ppc_trace[trace_model])
579 model_trace_make_busy(model_ptr, 0, out_mask, 0);
582 # Schedule an instruction that takes floating point input registers and produces an output fp register & sets a CR reg
583 void::model-function::ppc_insn_float_cr:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask, const unsigned32 cr_mask
584 const unsigned32 fp_mask = out_mask | in_mask;
585 model_busy *busy_ptr;
587 if ((model_ptr->fp_busy & fp_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
588 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
590 while ((model_ptr->fp_busy & fp_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
591 if (WITH_TRACE && ppc_trace[trace_model])
592 model_trace_busy_p(model_ptr, 0, fp_mask, cr_mask, PPC_NO_SPR);
594 model_ptr->nr_stalls_data++;
595 model_new_cycle(model_ptr);
599 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
600 model_ptr->fp_busy |= out_mask;
601 busy_ptr->fp_busy |= out_mask;
602 model_ptr->cr_fpscr_busy |= cr_mask;
603 busy_ptr->cr_fpscr_busy |= cr_mask;
604 busy_ptr->nr_writebacks = (cr_mask) ? 2 : 1;
605 if (WITH_TRACE && ppc_trace[trace_model])
606 model_trace_make_busy(model_ptr, 0, out_mask, cr_mask);
609 # Schedule an instruction that takes both int/float input registers and produces output int/float registers
610 void::model-function::ppc_insn_int_float:itable_index index, model_data *model_ptr, const unsigned32 out_int_mask, const unsigned32 out_fp_mask, const unsigned32 in_int_mask, const unsigned32 in_fp_mask
611 const unsigned32 int_mask = out_int_mask | in_int_mask;
612 const unsigned32 fp_mask = out_fp_mask | in_fp_mask;
613 model_busy *busy_ptr;
615 if ((model_ptr->int_busy & int_mask) || (model_ptr->fp_busy & fp_mask)) {
616 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
618 while ((model_ptr->int_busy & int_mask) || (model_ptr->fp_busy & fp_mask)) {
619 if (WITH_TRACE && ppc_trace[trace_model])
620 model_trace_busy_p(model_ptr, int_mask, fp_mask, 0, PPC_NO_SPR);
622 model_ptr->nr_stalls_data++;
623 model_new_cycle(model_ptr);
626 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
627 model_ptr->int_busy |= out_int_mask;
628 busy_ptr->int_busy |= out_int_mask;
629 model_ptr->fp_busy |= out_fp_mask;
630 busy_ptr->fp_busy |= out_fp_mask;
631 busy_ptr->nr_writebacks = ((out_int_mask) ? 1 : 0) + ((out_fp_mask) ? 1 : 0);
632 if (WITH_TRACE && ppc_trace[trace_model])
633 model_trace_make_busy(model_ptr, out_int_mask, out_fp_mask, 0);
637 # Schedule an MFSPR instruction that takes 1 special purpose register and produces an integer output register
638 void::model-function::ppc_insn_from_spr:itable_index index, model_data *model_ptr, const unsigned32 int_mask, const unsigned nSPR
639 model_busy *busy_ptr;
641 while ((model_ptr->int_busy & int_mask) != 0 || model_ptr->spr_busy[nSPR] != 0) {
642 if (WITH_TRACE && ppc_trace[trace_model])
643 model_trace_busy_p(model_ptr, int_mask, 0, 0, nSPR);
645 model_ptr->nr_stalls_data++;
646 model_new_cycle(model_ptr);
649 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
650 model_ptr->int_busy |= int_mask;
651 busy_ptr->int_busy |= int_mask;
652 busy_ptr->nr_writebacks = 1;
653 if (WITH_TRACE && ppc_trace[trace_model])
654 model_trace_make_busy(model_ptr, int_mask, 0, 0);
656 # Schedule an MTSPR instruction that takes 1 integer register and produces a special purpose output register
657 void::model-function::ppc_insn_to_spr:itable_index index, model_data *model_ptr, const unsigned32 int_mask, const unsigned nSPR
658 model_busy *busy_ptr;
660 while ((model_ptr->int_busy & int_mask) != 0 || model_ptr->spr_busy[nSPR] != 0) {
661 if (WITH_TRACE && ppc_trace[trace_model])
662 model_trace_busy_p(model_ptr, int_mask, 0, 0, nSPR);
664 model_ptr->nr_stalls_data++;
665 model_new_cycle(model_ptr);
668 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
669 busy_ptr->spr_busy = nSPR;
670 model_ptr->spr_busy[nSPR] = 1;
671 busy_ptr->nr_writebacks = 1;
672 TRACE(trace_model,("Making register %s busy.\n", spr_name(nSPR)));
674 # Schedule a MFCR instruction that moves the CR into an integer regsiter
675 void::model-function::ppc_insn_mfcr:itable_index index, model_data *model_ptr, unsigned32 int_mask
676 const unsigned32 cr_mask = 0xff;
677 model_busy *busy_ptr;
679 while (((model_ptr->int_busy & int_mask) | (model_ptr->cr_fpscr_busy & cr_mask)) != 0) {
680 if (WITH_TRACE && ppc_trace[trace_model])
681 model_trace_busy_p(model_ptr, int_mask, 0, cr_mask, PPC_NO_SPR);
683 model_ptr->nr_stalls_data++;
684 model_new_cycle(model_ptr);
687 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
688 model_ptr->int_busy |= int_mask;
689 busy_ptr->int_busy |= int_mask;
690 busy_ptr->nr_writebacks = 1;
691 if (WITH_TRACE && ppc_trace[trace_model])
692 model_trace_make_busy(model_ptr, int_mask, 0, 0);
694 # Schedule a MTCR instruction that moves an integer register into the CR
695 void::model-function::ppc_insn_mtcr:itable_index index, model_data *model_ptr, unsigned32 int_mask, unsigned FXM
698 unsigned32 cr_mask = 0;
699 const model_time *normal_time = &model_ptr->timing[index];
700 static const model_time ppc604_1bit_time = { PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 };
701 model_busy *busy_ptr;
703 for (f = 0; f < 8; f++) {
704 if (FXM & (0x80 >> f)) {
710 while (((model_ptr->int_busy & int_mask) | (model_ptr->cr_fpscr_busy & cr_mask)) != 0) {
711 if (WITH_TRACE && ppc_trace[trace_model])
712 model_trace_busy_p(model_ptr, int_mask, 0, cr_mask, PPC_NO_SPR);
714 model_ptr->nr_stalls_data++;
715 model_new_cycle(model_ptr);
718 /* If only one CR is being moved, use the SCIU, not the MCIU on the 604 */
719 if (CURRENT_MODEL == MODEL_ppc604 && nr_crs == 1) {
720 normal_time = &ppc604_1bit_time;
723 busy_ptr = model_wait_for_unit(index, model_ptr, normal_time);
724 busy_ptr->cr_fpscr_busy |= cr_mask;
725 model_ptr->cr_fpscr_busy |= cr_mask;
726 model_ptr->nr_mtcrf_crs[nr_crs]++;
727 busy_ptr->nr_writebacks = 1;
728 if (WITH_TRACE && ppc_trace[trace_model])
729 model_trace_make_busy(model_ptr, 0, 0, cr_mask);
731 model_data *::model-function::model_create:cpu *processor
732 model_data *model_ptr = ZALLOC(model_data);
733 model_ptr->name = model_name[CURRENT_MODEL];
734 model_ptr->timing = model_time_mapping[CURRENT_MODEL];
735 model_ptr->processor = processor;
736 model_ptr->nr_cycles = 1;
737 model_ptr->busy_tail = &model_ptr->busy_head;
738 switch (CURRENT_MODEL) {
739 case MODEL_ppc601: model_ptr->max_nr_writebacks = 1; break; /* ??? */
740 case MODEL_ppc603: model_ptr->max_nr_writebacks = 2; break;
741 case MODEL_ppc603e: model_ptr->max_nr_writebacks = 2; break;
742 case MODEL_ppc604: model_ptr->max_nr_writebacks = 2; break;
743 default: error ("Unknown model %d\n", CURRENT_MODEL);
747 void::model-function::model_init:model_data *model_ptr
749 void::model-function::model_halt:model_data *model_ptr
750 /* Let pipeline drain */
751 while (model_ptr->busy_head.next)
752 model_new_cycle(model_ptr);
754 unsigned_word::model-function::model_get_number_of_stalls:model_data *model_ptr
755 return (model_ptr->nr_stalls_data
756 + model_ptr->nr_stalls_unit
757 + model_ptr->nr_stalls_serialize
758 + model_ptr->nr_stalls_writeback);
760 unsigned_word::model-function::model_get_number_of_cycles:model_data *model_ptr
761 return (model_ptr->nr_cycles);
763 model_print *::model-function::model_mon_info:model_data *model_ptr
770 head = tail = ZALLOC(model_print);
771 tail->count = model_ptr->nr_cycles;
772 tail->name = "cycle";
773 tail->suffix_plural = "s";
774 tail->suffix_singular = "";
776 if (model_ptr->nr_stalls_data) {
777 tail->next = ZALLOC(model_print);
779 tail->count = model_ptr->nr_stalls_data;
780 tail->name = "stall";
781 tail->suffix_plural = "s waiting for data";
782 tail->suffix_singular = " waiting for data";
785 if (model_ptr->nr_stalls_unit) {
786 tail->next = ZALLOC(model_print);
788 tail->count = model_ptr->nr_stalls_unit;
789 tail->name = "stall";
790 tail->suffix_plural = "s waiting for a function unit";
791 tail->suffix_singular = " waiting for a function unit";
794 if (model_ptr->nr_stalls_serialize) {
795 tail->next = ZALLOC(model_print);
797 tail->count = model_ptr->nr_stalls_serialize;
798 tail->name = "stall";
799 tail->suffix_plural = "s waiting for serialization";
800 tail->suffix_singular = " waiting for serialization";
803 if (model_ptr->nr_stalls_writeback) {
804 tail->next = ZALLOC(model_print);
806 tail->count = model_ptr->nr_stalls_writeback;
808 tail->suffix_plural = "times a write-back slot was unavailable";
809 tail->suffix_singular = "time a writeback was unavilable";
812 if (model_ptr->nr_branches) {
813 tail->next = ZALLOC(model_print);
815 tail->count = model_ptr->nr_branches;
816 tail->name = "branch";
817 tail->suffix_plural = "es";
818 tail->suffix_singular = "";
821 if (model_ptr->nr_branches_fallthrough) {
822 tail->next = ZALLOC(model_print);
824 tail->count = model_ptr->nr_branches_fallthrough;
825 tail->name = "conditional branch";
826 tail->suffix_plural = "es fell through";
827 tail->suffix_singular = " fell through";
830 if (model_ptr->nr_branch_predict_trues) {
831 tail->next = ZALLOC(model_print);
833 tail->count = model_ptr->nr_branch_predict_trues;
834 tail->name = "successful branch prediction";
835 tail->suffix_plural = "s";
836 tail->suffix_singular = "";
839 if (model_ptr->nr_branch_predict_falses) {
840 tail->next = ZALLOC(model_print);
842 tail->count = model_ptr->nr_branch_predict_falses;
843 tail->name = "unsuccessful branch prediction";
844 tail->suffix_plural = "s";
845 tail->suffix_singular = "";
848 for (j = 0; j < (sizeof(ppc_branch_conditional_name) / sizeof(ppc_branch_conditional_name[0])) ; j++) {
849 if (model_ptr->nr_branch_conditional[j]) {
850 tail->next = ZALLOC(model_print);
852 tail->count = model_ptr->nr_branch_conditional[j];
853 tail->name = ppc_branch_conditional_name[j];
854 tail->suffix_plural = " conditional branches";
855 tail->suffix_singular = " conditional branch";
859 for (j = 0; j < 9; j++) {
860 if (model_ptr->nr_mtcrf_crs[j]) {
861 tail->next = ZALLOC(model_print);
863 tail->count = model_ptr->nr_mtcrf_crs[j];
864 tail->name = ppc_nr_mtcrf_crs[j];
865 tail->suffix_plural = " instructions";
866 tail->suffix_singular = " instruction";
871 for (i = PPC_UNIT_BAD; i < nr_ppc_function_units; i++) {
872 if (model_ptr->nr_units[i]) {
873 nr_insns += model_ptr->nr_units[i];
874 tail->next = ZALLOC(model_print);
876 tail->count = model_ptr->nr_units[i];
877 tail->name = ppc_function_unit_name[i];
878 tail->suffix_plural = "s";
879 tail->suffix_singular = "";
883 tail->next = ZALLOC(model_print);
885 tail->count = nr_insns;
886 tail->name = "instruction";
887 tail->suffix_plural = "s that were accounted for in timing info";
888 tail->suffix_singular = " that was accounted for in timing info";
890 tail->next = (model_print *)0;
893 void::model-function::model_mon_info_free:model_data *model_ptr, model_print *ptr
895 model_print *next = ptr->next;
900 void::model-function::model_branches:model_data *model_ptr, int failed, int conditional
901 model_ptr->nr_units[PPC_UNIT_BPU]++;
903 model_ptr->nr_branches_fallthrough++;
905 model_ptr->nr_branches++;
906 if (conditional >= 0)
907 model_ptr->nr_branch_conditional[conditional]++;
908 model_new_cycle(model_ptr); /* A branch always ends the current cycle */
910 void::model-function::model_branch_predict:model_data *model_ptr, int success
912 model_ptr->nr_branch_predict_trues++;
914 model_ptr->nr_branch_predict_falses++;
917 # The following (illegal) instruction is `known' by gen and is
918 # called when ever an illegal instruction is encountered
920 program_interrupt(processor, cia,
921 illegal_instruction_program_interrupt);
924 # The following (floating point unavailable) instruction is `known' by gen
925 # and is called when ever an a floating point instruction is to be
926 # executed but floating point is make unavailable by the MSR
927 ::internal::floating_point_unavailable
928 floating_point_unavailable_interrupt(processor, cia);
932 # Floating point support functions
935 # Convert 32bit single to 64bit double
936 unsigned64::function::DOUBLE:unsigned32 WORD
938 if (EXTRACTED32(WORD, 1, 8) > 0
939 && EXTRACTED32(WORD, 1, 8) < 255) {
940 /* normalized operand */
941 int not_word_1_1 = !EXTRACTED32(WORD, 1, 1); /*2.6.3 bug*/
942 FRT = (INSERTED64(EXTRACTED32(WORD, 0, 1), 0, 1)
943 | INSERTED64(not_word_1_1, 2, 2)
944 | INSERTED64(not_word_1_1, 3, 3)
945 | INSERTED64(not_word_1_1, 4, 4)
946 | INSERTED64(EXTRACTED32(WORD, 2, 31), 5, (63 - 29)));
948 else if (EXTRACTED32(WORD, 1, 8) == 0
949 && EXTRACTED32(WORD, 9, 31) != 0) {
950 /* denormalized operand */
951 int sign = EXTRACTED32(WORD, 0, 0);
953 unsigned64 frac = INSERTED64(EXTRACTED32(WORD, 9, 31), 1, (52 - 29));
954 /* normalize the operand */
955 while (MASKED64(frac, 0, 0) == 0) {
959 FRT = (INSERTED64(sign, 0, 0)
960 | INSERTED64(exp + 1023, 1, 11)
961 | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
963 else if (EXTRACTED32(WORD, 1, 8) == 255
964 || EXTRACTED32(WORD, 1, 31) == 0) {
965 FRT = (INSERTED64(EXTRACTED32(WORD, 0, 1), 0, 1)
966 | INSERTED64(EXTRACTED32(WORD, 1, 1), 2, 2)
967 | INSERTED64(EXTRACTED32(WORD, 1, 1), 3, 3)
968 | INSERTED64(EXTRACTED32(WORD, 1, 1), 4, 4)
969 | INSERTED64(EXTRACTED32(WORD, 2, 31), 5, (63 - 29)));
972 error("DOUBLE - unknown case\n");
977 # Convert 64bit single to 32bit double
978 unsigned32::function::SINGLE:unsigned64 FRS
980 if (EXTRACTED64(FRS, 1, 11) > 896
981 || EXTRACTED64(FRS, 1, 63) == 0) {
982 /* no denormalization required (includes Zero/Infinity/NaN) */
983 WORD = (INSERTED32(EXTRACTED64(FRS, 0, 1), 0, 1)
984 | INSERTED32(EXTRACTED64(FRS, 5, 34), 2, 31));
986 else if (874 <= EXTRACTED64(FRS, 1, 11)
987 && EXTRACTED64(FRS, 1, 11) <= 896) {
988 /* denormalization required */
989 int sign = EXTRACTED64(FRS, 0, 0);
990 int exp = EXTRACTED64(FRS, 1, 11) - 1023;
991 unsigned64 frac = (BIT64(0)
992 | INSERTED64(EXTRACTED64(FRS, 12, 63), 1, 52));
993 /* denormalize the operand */
995 frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63);
998 WORD = (INSERTED32(sign, 0, 0)
999 | INSERTED32(0x00, 1, 8)
1000 | INSERTED32(EXTRACTED64(frac, 1, 23), 9, 31));
1003 WORD = 0x0; /* ??? */
1008 # round 64bit double to 64bit but single
1009 void::function::Round_Single:cpu *processor, int sign, int *exp, unsigned64 *frac_grx
1010 /* comparisons ignore u bits */
1013 int lsb = EXTRACTED64(*frac_grx, 23, 23);
1014 int gbit = EXTRACTED64(*frac_grx, 24, 24);
1015 int rbit = EXTRACTED64(*frac_grx, 25, 25);
1016 int xbit = EXTRACTED64(*frac_grx, 26, 55) != 0;
1017 if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
1018 if (lsb == 1 && gbit == 1) inc = 1;
1019 if (lsb == 0 && gbit == 1 && rbit == 1) inc = 1;
1020 if (lsb == 0 && gbit == 1 && xbit == 1) inc = 1;
1022 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_pos_infinity) {
1023 if (sign == 0 && gbit == 1) inc = 1;
1024 if (sign == 0 && rbit == 1) inc = 1;
1025 if (sign == 0 && xbit == 1) inc = 1;
1027 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_neg_infinity) {
1028 if (sign == 1 && gbit == 1) inc = 1;
1029 if (sign == 1 && rbit == 1) inc = 1;
1030 if (sign == 1 && xbit == 1) inc = 1;
1032 /* work out addition in low 25 bits of out */
1033 out = EXTRACTED64(*frac_grx, 0, 23) + inc;
1034 *frac_grx = INSERTED64(out, 0, 23);
1035 if (out & BIT64(64 - 23 - 1 - 1)) {
1036 *frac_grx = (BIT64(0) |
1037 INSERTED64(EXTRACTED64(*frac_grx, 0, 22), 1, 23));
1040 /* frac_grx[24:52] = 0 already */
1042 FPSCR_SET_FI(gbit || rbit || xbit);
1046 void::function::Round_Integer:cpu *processor, int sign, unsigned64 *frac, int *frac64, int gbit, int rbit, int xbit, fpscreg round_mode
1048 if (round_mode == fpscr_rn_round_to_nearest) {
1049 if (*frac64 == 1 && gbit == 1) inc = 1;
1050 if (*frac64 == 0 && gbit == 1 && rbit == 1) inc = 1;
1051 if (*frac64 == 0 && gbit == 1 && xbit == 1) inc = 1;
1053 if (round_mode == fpscr_rn_round_towards_pos_infinity) {
1054 if (sign == 0 && gbit == 1) inc = 1;
1055 if (sign == 0 && rbit == 1) inc = 1;
1056 if (sign == 0 && xbit == 1) inc = 1;
1058 if (round_mode == fpscr_rn_round_towards_neg_infinity) {
1059 if (sign == 1 && gbit == 1) inc = 1;
1060 if (sign == 1 && rbit == 1) inc = 1;
1061 if (sign == 1 && xbit == 1) inc = 1;
1063 /* frac[0:64] = frac[0:64} + inc */
1064 *frac += (*frac64 && inc ? 1 : 0);
1065 *frac64 = (*frac64 + inc) & 0x1;
1067 FPSCR_SET_FI(gbit | rbit | xbit);
1070 void::function::Round_Float:cpu *processor, int sign, int *exp, unsigned64 *frac, fpscreg round_mode
1073 int lsb = EXTRACTED64(*frac, 52, 52);
1074 int gbit = EXTRACTED64(*frac, 53, 53);
1075 int rbit = EXTRACTED64(*frac, 54, 54);
1076 int xbit = EXTRACTED64(*frac, 55, 55);
1077 if (round_mode == fpscr_rn_round_to_nearest) {
1078 if (lsb == 1 && gbit == 1) inc = 1;
1079 if (lsb == 0 && gbit == 1 && rbit == 1) inc = 1;
1080 if (lsb == 0 && gbit == 1 && xbit == 1) inc = 1;
1082 if (round_mode == fpscr_rn_round_towards_pos_infinity) {
1083 if (sign == 0 && gbit == 1) inc = 1;
1084 if (sign == 0 && rbit == 1) inc = 1;
1085 if (sign == 0 && xbit == 1) inc = 1;
1087 if (round_mode == fpscr_rn_round_towards_neg_infinity) {
1088 if (sign == 1 && gbit == 1) inc = 1;
1089 if (sign == 1 && rbit == 1) inc = 1;
1090 if (sign == 1 && xbit == 1) inc = 1;
1092 /* frac//carry_out = frac + inc */
1093 *frac = (*frac >> 1) + (INSERTED64(inc, 52, 52) >> 1);
1094 carry_out = EXTRACTED64(*frac, 0, 0);
1096 if (carry_out == 1) *exp = *exp + 1;
1098 FPSCR_SET_FI(gbit | rbit | xbit);
1099 FPSCR_SET_XX(FPSCR & fpscr_fi);
1102 # conversion of FP to integer
1103 void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64 *frt, unsigned64 frb, fpscreg round_mode, int tgt_precision
1106 unsigned64 frac = 0;
1111 int sign = EXTRACTED64(frb, 0, 0);
1113 if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 63) == 0)
1114 GOTO(Infinity_Operand);
1115 if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 0)
1117 if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 1)
1119 if (EXTRACTED64(frb, 1, 11) > 1086) GOTO(Large_Operand);
1120 if (EXTRACTED64(frb, 1, 11) > 0) exp = EXTRACTED64(frb, 1, 11) - 1023;
1121 if (EXTRACTED64(frb, 1, 11) == 0) exp = -1022;
1122 if (EXTRACTED64(frb, 1, 11) > 0) { /* normal */
1123 frac = BIT64(1) | INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
1126 if (EXTRACTED64(frb, 1, 11) == 0) { /* denorm */
1127 frac = INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
1130 gbit = 0, rbit = 0, xbit = 0;
1131 for (i = 1; i <= 63 - exp; i++) {
1135 frac64 = EXTRACTED64(frac, 63, 63);
1136 frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63);
1138 Round_Integer(processor, sign, &frac, &frac64, gbit, rbit, xbit, round_mode);
1139 if (sign == 1) { /* frac[0:64] = ~frac[0:64] + 1 */
1142 frac += (frac64 ? 1 : 0);
1143 frac64 = (frac64 + 1) & 0x1;
1145 if (tgt_precision == 32 /* can ignore frac64 in compare */
1146 && (signed64)frac > (signed64)MASK64(33+1, 63)/*2^31-1 >>1*/)
1147 GOTO(Large_Operand);
1148 if (tgt_precision == 64 /* can ignore frac64 in compare */
1149 && (signed64)frac > (signed64)MASK64(1+1, 63)/*2^63-1 >>1*/)
1150 GOTO(Large_Operand);
1151 if (tgt_precision == 32 /* can ignore frac64 in compare */
1152 && (signed64)frac < (signed64)MASK64(0, 32+1)/*-2^31 >>1*/)
1153 GOTO(Large_Operand);
1154 if (tgt_precision == 64 /* can ignore frac64 in compare */
1155 && (signed64)frac < (signed64)MASK64(0, 0+1)/*-2^63 >>1*/)
1156 GOTO(Large_Operand);
1157 FPSCR_SET_XX(FPSCR & fpscr_fi);
1158 if (tgt_precision == 32)
1159 *frt = MASKED64(*frt, 0, 31) | (EXTRACTED64(frac, 33, 63) << 1) | frac64;
1160 if (tgt_precision == 64)
1161 *frt = (EXTRACTED64(frac, 1, 63) << 1) | frac64;
1162 /*FPSCR[fprf] = undefined */
1165 LABEL(Infinity_Operand):
1168 FPSCR_OR_VX(fpscr_vxcvi);
1169 if ((FPSCR & fpscr_ve) == 0) {
1170 if (tgt_precision == 32) {
1171 if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7FFFFFFF;
1172 if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1175 if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/
1176 if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
1178 /* FPSCR[FPRF] = undefined */
1182 LABEL(SNaN_Operand):
1185 FPSCR_OR_VX(fpscr_vxsnan | fpscr_vxcvi);
1186 if ((FPSCR & fpscr_ve) == 0) {
1187 if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1188 if (tgt_precision == 64) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
1189 /* FPSCR[fprf] = undefined */
1193 LABEL(QNaN_Operand):
1196 FPSCR_OR_VX(fpscr_vxcvi);
1197 if ((FPSCR & fpscr_ve) == 0) {
1198 if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1199 if (tgt_precision == 64) *frt = BIT64(0);/*0x8000_0000_0000_0000*/
1200 /* FPSCR[fprf] = undefined */
1204 LABEL(Large_Operand):
1207 FPSCR_OR_VX(fpscr_vxcvi);
1208 if ((FPSCR & fpscr_ve) == 0) {
1209 if (tgt_precision == 32) {
1210 if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7fffffff;
1211 if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1214 if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/
1215 if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
1217 /* FPSCR[fprf] = undefined */
1223 # extract out raw fields of a FP number
1224 int::function::sign:unsigned64 FRS
1225 return (MASKED64(FRS, 0, 0)
1228 int::function::biased_exp:unsigned64 frs, int single
1230 return EXTRACTED64(frs, 1, 8);
1232 return EXTRACTED64(frs, 1, 11);
1233 unsigned64::function::fraction:unsigned64 frs, int single
1235 return EXTRACTED64(frs, 9, 31);
1237 return EXTRACTED64(frs, 12, 63);
1239 # a number?, each of the below return +1 or -1 (based on sign bit)
1241 int::function::is_nor:unsigned64 frs, int single
1242 int exp = biased_exp(frs, single);
1244 && exp <= (single ? 254 : 2046));
1245 int::function::is_zero:unsigned64 FRS
1246 return (MASKED64(FRS, 1, 63) == 0
1249 int::function::is_den:unsigned64 frs, int single
1250 int exp = biased_exp(frs, single);
1251 unsigned64 frac = fraction(frs, single);
1252 return (exp == 0 && frac != 0
1255 int::function::is_inf:unsigned64 frs, int single
1256 int exp = biased_exp(frs, single);
1257 int frac = fraction(frs, single);
1258 return (exp == (single ? 255 : 2047) && frac == 0
1261 int::function::is_NaN:unsigned64 frs, int single
1262 int exp = biased_exp(frs, single);
1263 int frac = fraction(frs, single);
1264 return (exp == (single ? 255 : 2047) && frac != 0
1267 int::function::is_SNaN:unsigned64 frs, int single
1268 return (is_NaN(frs, single)
1269 && !(frs & (single ? MASK64(9, 9) : MASK64(12, 12)))
1272 int::function::is_QNaN:unsigned64 frs, int single
1273 return (is_NaN(frs, single) && !is_SNaN(frs, single));
1274 int::function::is_less_than:unsigned64 *fra, unsigned64 *frb
1275 return *(double*)fra < *(double*)frb;
1276 int::function::is_greater_than:unsigned64 *fra, unsigned64 *frb
1277 return *(double*)fra > *(double*)frb;
1278 int::function::is_equan_to:unsigned64 *fra, unsigned64 *frb
1279 return *(double*)fra == *(double*)frb;
1282 # which quiet nan should become the result
1283 unsigned64::function::select_qnan:unsigned64 fra, unsigned64 frb, unsigned64 frc, int instruction_is_frsp, int generate_qnan, int single
1285 if (is_NaN(fra, single))
1287 else if (is_NaN(frb, single))
1288 if (instruction_is_frsp)
1289 frt = MASKED64(frb, 0, 34);
1292 else if (is_NaN(frc, single))
1294 else if (generate_qnan)
1295 frt = MASK64(1, 12); /* 0x7FF8_0000_0000_0000 */
1297 error("select_qnan - default reached\n");
1301 # detect invalid operation
1302 int::function::is_invalid_operation:cpu *processor, unsigned_word cia, unsigned64 fra, unsigned64 frb, fpscreg check, int single, int negate
1304 if ((check & fpscr_vxsnan)
1305 && (is_SNaN(fra, single) || is_SNaN(frb, single))) {
1306 FPSCR_OR_VX(fpscr_vxsnan);
1309 if ((check & fpscr_vxisi)
1310 && (is_inf(fra, single) && is_inf(frb, single))
1311 && ((negate && sign(fra) != sign(frb))
1312 || (!negate && sign(fra) == sign(frb)))) {
1313 /*FIXME: don't handle inf-inf VS inf+-inf */
1314 FPSCR_OR_VX(fpscr_vxisi);
1317 if ((check & fpscr_vxidi)
1318 && (is_inf(fra, single) && is_inf(frb, single))) {
1319 FPSCR_OR_VX(fpscr_vxidi);
1322 if ((check & fpscr_vxzdz)
1323 && (is_zero(fra) && is_zero(frb))) {
1324 FPSCR_OR_VX(fpscr_vxzdz);
1327 if ((check & fpscr_vximz)
1328 && (is_zero(fra) && is_inf(frb, single))) {
1329 FPSCR_OR_VX(fpscr_vximz);
1332 if ((check & fpscr_vxvc)
1333 && (is_NaN(fra, single) || is_NaN(frb, single))) {
1334 FPSCR_OR_VX(fpscr_vxvc);
1337 if ((check & fpscr_vxsoft)) {
1338 FPSCR_OR_VX(fpscr_vxsoft);
1341 if ((check & fpscr_vxsqrt)
1343 FPSCR_OR_VX(fpscr_vxsqrt);
1346 /* if ((check && fpscr_vxcvi) {
1347 && (is_inf(fra, single) || is_NaN(fra, single) || is_large(fra, single)))
1348 FPSCR_OR_VX(fpscr_vxcvi);
1358 # handle case of invalid operation
1359 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
1360 if (FPSCR & fpscr_ve) {
1361 /* invalid operation exception enabled */
1365 /* fpscr_FPRF unchanged */
1368 /* invalid operation exception disabled */
1369 if (instruction_is_convert_to_64bit) {
1372 else if (instruction_is_convert_to_32bit) {
1375 else { /* arrith, frsp */
1376 *frt = select_qnan(fra, frb, frc,
1377 instruction_is_frsp, 0/*generate*/, single);
1380 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
1388 # 0.0.0.0 Illegal instruction used for kernel mode emulation
1390 0.0,6./,11./,16./,21./,31.1:X:::instruction_call
1391 if (!os_emul_instruction_call(processor, cia, real_addr(cia, 1)))
1392 program_interrupt(processor, cia,
1393 illegal_instruction_program_interrupt);
1396 # I.2.4.1 Branch Instructions
1398 0.18,6.LI,30.AA,31.LK:I:::Branch
1399 *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1400 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1401 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1402 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1403 if (AA) NIA = IEA(EXTS(LI_0b00));
1404 else NIA = IEA(CIA + EXTS(LI_0b00));
1405 if (LK) LR = (spreg)CIA+4;
1406 if (CURRENT_MODEL_ISSUE > 0)
1407 model_branches(cpu_model(processor), 1, -1);
1409 0.16,6.BO,11.BI,16.BD,30.AA,31.LK:B:::Branch Conditional
1410 *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1411 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1412 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1413 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1414 int M, ctr_ok, cond_ok, succeed;
1415 if (CURRENT_MODEL_ISSUE > 0 && ! BO{0})
1416 model_wait_for_cr(cpu_model(processor), BIT32_BI);
1417 if (is_64bit_implementation && is_64bit_mode) M = 0;
1419 if (!BO{2}) CTR = CTR - 1;
1420 ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != (BO{3}));
1421 cond_ok = BO{0} || ((CR{BI}) == (BO{1}));
1422 if (ctr_ok && cond_ok) {
1423 if (AA) NIA = IEA(EXTS(BD_0b00));
1424 else NIA = IEA(CIA + EXTS(BD_0b00));
1429 if (LK) LR = (spreg)IEA(CIA + 4);
1430 if (CURRENT_MODEL_ISSUE > 0)
1431 model_branches(cpu_model(processor), succeed, BO);
1434 if (BO{4}) { /* branch prediction bit set, reverse sense of test */
1435 reverse = EXTS(BD_0b00) < 0;
1436 } else { /* branch prediction bit not set */
1437 reverse = EXTS(BD_0b00) >= 0;
1439 if (CURRENT_MODEL_ISSUE > 0)
1440 model_branch_predict(cpu_model(processor), reverse ? !succeed : succeed);
1443 0.19,6.BO,11.BI,16./,21.16,31.LK:XL:::Branch Conditional to Link Register
1444 *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1445 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1446 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1447 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1448 int M, ctr_ok, cond_ok, succeed;
1449 if (is_64bit_implementation && is_64bit_mode) M = 0;
1451 if (CURRENT_MODEL_ISSUE > 0 && ! BO{0})
1452 model_wait_for_cr(cpu_model(processor), BIT32_BI);
1453 if (!BO{2}) CTR = CTR - 1;
1454 ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != BO{3});
1455 cond_ok = BO{0} || (CR{BI} == BO{1});
1456 if (ctr_ok && cond_ok) {
1462 if (LK) LR = (spreg)IEA(CIA + 4);
1463 if (CURRENT_MODEL_ISSUE > 0) {
1464 model_branches(cpu_model(processor), succeed, BO);
1466 model_branch_predict(cpu_model(processor), BO{4} ? !succeed : succeed);
1469 0.19,6.BO,11.BI,16./,21.528,31.LK:XL:::Branch Conditional to Count Register
1470 *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1471 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1472 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1473 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1474 int cond_ok, succeed;
1475 if (CURRENT_MODEL_ISSUE > 0 && ! BO{0})
1476 model_wait_for_cr(cpu_model(processor), BIT32_BI);
1477 cond_ok = BO{0} || (CR{BI} == BO{1});
1479 NIA = IEA(CTR_0b00);
1484 if (LK) LR = (spreg)IEA(CIA + 4);
1485 if (CURRENT_MODEL_ISSUE > 0) {
1486 model_branches(cpu_model(processor), succeed, BO);
1488 model_branch_predict(cpu_model(processor), BO{4} ? !succeed : succeed);
1492 # I.2.4.2 System Call Instruction
1494 0.17,6./,11./,16./,30.1,31./:SC:::System Call
1495 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1496 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
1497 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
1498 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1499 if (CURRENT_MODEL_ISSUE > 0)
1500 model_serialize(MY_INDEX, cpu_model(processor));
1501 system_call_interrupt(processor, cia);
1504 # I.2.4.3 Condition Register Logical Instructions
1506 0.19,6.BT,11.BA,16.BB,21.257,31./:XL::crand:Condition Register AND
1507 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1508 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1509 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1510 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1511 BLIT32(CR, BT, CR{BA} && CR{BB});
1512 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1514 0.19,6.BT,11.BA,16.BB,21.449,31./:XL::cror:Condition Register OR
1515 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1516 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1517 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1518 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1519 BLIT32(CR, BT, CR{BA} || CR{BB});
1520 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1522 0.19,6.BT,11.BA,16.BB,21.193,31./:XL::crxor:Condition Register XOR
1523 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1524 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1525 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1526 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1527 BLIT32(CR, BT, CR{BA} != CR{BB});
1528 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1530 0.19,6.BT,11.BA,16.BB,21.225,31./:XL::crnand:Condition Register NAND
1531 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1532 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1533 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1534 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1535 BLIT32(CR, BT, !(CR{BA} && CR{BB}));
1536 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1538 0.19,6.BT,11.BA,16.BB,21.33,31./:XL::crnor:Condition Register NOR
1539 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1540 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1541 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1542 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1543 BLIT32(CR, BT, !(CR{BA} || CR{BB}));
1544 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1546 0.19,6.BT,11.BA,16.BB,21.289,31./:XL::creqv:Condition Register Equivalent
1547 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1548 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1549 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1550 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1551 BLIT32(CR, BT, CR{BA} == CR{BB});
1552 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1554 0.19,6.BT,11.BA,16.BB,21.129,31./:XL::crandc:Condition Register AND with Complement
1555 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1556 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1557 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1558 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1559 BLIT32(CR, BT, CR{BA} && !CR{BB});
1560 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1562 0.19,6.BT,11.BA,16.BB,21.417,31./:XL::crorc:Condition Register OR with Complement
1563 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1564 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1565 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1566 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1567 BLIT32(CR, BT, CR{BA} || !CR{BB});
1568 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1571 # I.2.4.4 Condition Register Field Instruction
1573 0.19,6.BF,9./,11.BFA,14./,16./,21.0,31./:XL:::Move Condition Register Field
1574 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1575 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1576 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1577 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1578 MBLIT32(CR, 4*BF, 4*BF+3, EXTRACTED32(CR, 4*BFA, 4*BFA+3));
1579 PPC_INSN_CR(BF_BITMASK, 1 << BFA);
1583 # I.3.3.2 Fixed-Point Load Instructions
1586 0.34,6.RT,11.RA,16.D:D:::Load Byte and Zero
1587 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1588 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1589 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1590 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1596 *rT = MEM(unsigned, EA, 1);
1597 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
1600 0.31,6.RT,11.RA,16.RB,21.87,31./:X:::Load Byte and Zero Indexed
1601 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1602 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1603 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1604 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1610 *rT = MEM(unsigned, EA, 1);
1611 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
1613 0.35,6.RT,11.RA,16.D:D:::Load Byte and Zero with Update
1614 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1615 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1616 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1617 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1619 if (RA == 0 || RA == RT)
1620 program_interrupt(processor, cia,
1621 illegal_instruction_program_interrupt);
1623 *rT = MEM(unsigned, EA, 1);
1625 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK, 0);
1627 0.31,6.RT,11.RA,16.RB,21.119,31./:X:::Load Byte and Zero with Update Indexed
1628 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1629 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1630 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1631 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1633 if (RA == 0 || RA == RT)
1634 program_interrupt(processor, cia,
1635 illegal_instruction_program_interrupt);
1637 *rT = MEM(unsigned, EA, 1);
1639 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK | RB_BITMASK, 0);
1641 0.40,6.RT,11.RA,16.D:D:::Load Halfword and Zero
1642 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1643 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1644 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1645 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1651 *rT = MEM(unsigned, EA, 2);
1652 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
1654 0.31,6.RT,11.RA,16.RB,21.279,31./:X:::Load Halfword and Zero Indexed
1655 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1656 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1657 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1658 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1664 *rT = MEM(unsigned, EA, 2);
1665 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
1667 0.41,6.RT,11.RA,16.D:D:::Load Halfword and Zero with Update
1668 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1669 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1670 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1671 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1673 if (RA == 0 || RA == RT)
1674 program_interrupt(processor, cia,
1675 illegal_instruction_program_interrupt);
1677 *rT = MEM(unsigned, EA, 2);
1679 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK, 0);
1681 0.31,6.RT,11.RA,16.RB,21.311,31./:X:::Load Halfword and Zero with Update Indexed
1682 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1683 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1684 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1685 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1687 if (RA == 0 || RA == RT)
1688 program_interrupt(processor, cia,
1689 illegal_instruction_program_interrupt);
1691 *rT = MEM(unsigned, EA, 2);
1693 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK | RB_BITMASK, 0);
1695 0.42,6.RT,11.RA,16.D:D:::Load Halfword Algebraic
1696 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1697 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1698 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1699 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1705 *rT = MEM(signed, EA, 2);
1706 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
1708 0.31,6.RT,11.RA,16.RB,21.343,31./:X:::Load Halfword Algebraic Indexed
1709 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1710 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1711 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1712 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1718 *rT = MEM(signed, EA, 2);
1719 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
1721 0.43,6.RT,11.RA,16.D:D:::Load Halfword Algebraic with Update
1722 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1723 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1724 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1725 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1727 if (RA == 0 || RA == RT)
1728 program_interrupt(processor, cia,
1729 illegal_instruction_program_interrupt);
1731 *rT = MEM(signed, EA, 2);
1732 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK, 0);
1734 0.31,6.RT,11.RA,16.RB,21.375,31./:X:::Load Halfword Algebraic with Update Indexed
1735 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1736 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1737 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1738 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1740 if (RA == 0 || RA == RT)
1741 program_interrupt(processor, cia,
1742 illegal_instruction_program_interrupt);
1744 *rT = MEM(signed, EA, 2);
1746 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK | RB_BITMASK, 0);
1748 0.32,6.RT,11.RA,16.D:D:::Load Word and Zero
1749 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 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, 2, 0
1758 *rT = MEM(unsigned, EA, 4);
1759 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
1761 0.31,6.RT,11.RA,16.RB,21.23,31./:X:::Load Word and Zero Indexed
1762 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1763 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1764 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1765 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1771 *rT = MEM(unsigned, EA, 4);
1772 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
1774 0.33,6.RT,11.RA,16.D:D:::Load Word and Zero with Update
1775 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1776 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1777 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1778 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1780 if (RA == 0 || RA == RT)
1781 program_interrupt(processor, cia,
1782 illegal_instruction_program_interrupt);
1784 *rT = MEM(unsigned, EA, 4);
1786 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK, 0);
1788 0.31,6.RT,11.RA,16.RB,21.55,31./:X:::Load Word and Zero with Update Indexed
1789 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1790 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1791 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1792 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1794 if (RA == 0 || RA == RT)
1795 program_interrupt(processor, cia,
1796 illegal_instruction_program_interrupt);
1798 *rT = MEM(unsigned, EA, 4);
1800 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK | RB_BITMASK, 0);
1802 0.58,6.RT,11.RA,16.DS,30.2:DS:64::Load Word Algebraic
1805 # if (RA == 0) b = 0;
1807 # EA = b + EXTS(DS_0b00);
1808 # *rT = MEM(signed, EA, 4);
1810 0.31,6.RT,11.RA,16.RB,21.341,31./:X:64::Load Word Algebraic Indexed
1813 # if (RA == 0) b = 0;
1816 # *rT = MEM(signed, EA, 4);
1818 0.31,6.RT,11.RA,16.RB,21.373,31./:X:64::Load Word Algebraic with Update Indexed
1820 # if (RA == 0 || RA == RT)
1821 # program_interrupt(processor, cia
1822 # illegal_instruction_program_interrupt);
1824 # *rT = MEM(signed, EA, 4);
1827 0.58,6.RT,11.RA,16.DS,30.0:DS:64::Load Doubleword
1830 # if (RA == 0) b = 0;
1832 # EA = b + EXTS(DS_0b00);
1833 # *rT = MEM(unsigned, EA, 8);
1835 0.31,6.RT,11.RA,16.RB,21.21,31./:X:64::Load Doubleword Indexed
1838 # if (RA == 0) b = 0;
1841 # *rT = MEM(unsigned, EA, 8);
1843 0.58,6.RT,11.RA,16.DS,30.1:DS:64::Load Doubleword with Update
1845 # if (RA == 0 || RA == RT)
1846 # program_interrupt(processor, cia
1847 # illegal_instruction_program_interrupt);
1848 # EA = *rA + EXTS(DS_0b00);
1849 # *rT = MEM(unsigned, EA, 8);
1852 0.31,6.RT,11.RA,16.RB,21.53,31./:DS:64::Load Doubleword with Update Indexed
1854 # if (RA == 0 || RA == RT)
1855 # program_interrupt(processor, cia
1856 # illegal_instruction_program_interrupt);
1858 # *rT = MEM(unsigned, EA, 8);
1864 # I.3.3.3 Fixed-Point Store Instructions
1867 0.38,6.RS,11.RA,16.D:D:::Store Byte
1868 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1869 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1870 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1871 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1878 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RS_BITMASK, 0);
1880 0.31,6.RS,11.RA,16.RB,21.215,31./:X:::Store Byte Indexed
1881 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1882 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1883 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1884 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1891 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
1893 0.39,6.RS,11.RA,16.D:D:::Store Byte with Update
1894 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1895 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1896 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1897 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1900 program_interrupt(processor, cia,
1901 illegal_instruction_program_interrupt);
1905 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RS_BITMASK, 0);
1907 0.31,6.RS,11.RA,16.RB,21.247,31./:X:::Store Byte with Update Indexed
1908 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1909 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1910 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1911 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1914 program_interrupt(processor, cia,
1915 illegal_instruction_program_interrupt);
1919 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RB_BITMASK | RS_BITMASK, 0);
1921 0.44,6.RS,11.RA,16.D:D:::Store Half Word
1922 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1923 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1924 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1925 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1932 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RS_BITMASK, 0);
1934 0.31,6.RS,11.RA,16.RB,21.407,31./:X:::Store Half Word Indexed
1935 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1936 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1937 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1938 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1945 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
1947 0.45,6.RS,11.RA,16.D:D:::Store Half Word with Update
1948 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1949 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1950 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1951 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1954 program_interrupt(processor, cia,
1955 illegal_instruction_program_interrupt);
1959 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RS_BITMASK, 0);
1961 0.31,6.RS,11.RA,16.RB,21.439,31./:X:::Store Half Word with Update Indexed
1962 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1963 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1964 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1965 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1968 program_interrupt(processor, cia,
1969 illegal_instruction_program_interrupt);
1973 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RB_BITMASK | RS_BITMASK, 0);
1975 0.36,6.RS,11.RA,16.D:D:::Store Word
1976 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1977 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1978 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1979 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1986 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RS_BITMASK, 0);
1988 0.31,6.RS,11.RA,16.RB,21.151,31./:X:::Store Word Indexed
1989 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1990 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1991 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1992 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1999 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
2001 0.37,6.RS,11.RA,16.D:D:::Store Word with Update
2002 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2003 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2004 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2005 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2008 program_interrupt(processor, cia,
2009 illegal_instruction_program_interrupt);
2013 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RS_BITMASK, 0);
2015 0.31,6.RS,11.RA,16.RB,21.183,31./:X:::Store Word with Update Indexed
2016 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2017 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2018 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2019 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2022 program_interrupt(processor, cia,
2023 illegal_instruction_program_interrupt);
2027 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RB_BITMASK | RS_BITMASK, 0);
2029 0.62,6.RS,11.RA,16.DS,30.0:DS:64::Store Doubleword
2032 # if (RA == 0) b = 0;
2034 # EA = b + EXTS(DS_0b00);
2035 # STORE(EA, 8, *rS);
2036 0.31,6.RS,11.RA,16.RB,21.149,31./:X:64::Store Doubleword Indexed
2039 # if (RA == 0) b = 0;
2042 # STORE(EA, 8, *rS);
2043 0.62,6.RS,11.RA,16.DS,30.1:DS:64::Store Doubleword with Update
2046 # program_interrupt(processor, cia
2047 # illegal_instruction_program_interrupt);
2048 # EA = *rA + EXTS(DS_0b00);
2049 # STORE(EA, 8, *rS);
2051 0.31,6.RS,11.RA,16.RB,21.181,31./:X:64::Store Doubleword with Update Indexed
2054 # program_interrupt(processor, cia
2055 # illegal_instruction_program_interrupt);
2057 # STORE(EA, 8, *rS);
2062 # I.3.3.4 Fixed-Point Load and Store with Byte Reversal Instructions
2065 0.31,6.RT,11.RA,16.RB,21.790,31./:X:::Load Halfword Byte-Reverse Indexed
2066 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2067 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2068 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2069 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2075 *rT = SWAP_2(MEM(unsigned, EA, 2));
2076 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
2078 0.31,6.RT,11.RA,16.RB,21.534,31./:X:::Load Word Byte-Reverse Indexed
2079 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2080 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2081 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2082 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2088 *rT = SWAP_4(MEM(unsigned, EA, 4));
2089 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
2091 0.31,6.RS,11.RA,16.RB,21.918,31./:X:::Store Half Word Byte-Reversed Indexed
2092 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2093 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2094 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2095 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2101 STORE(EA, 2, SWAP_2(*rS));
2102 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
2104 0.31,6.RS,11.RA,16.RB,21.662,31./:X:::Store Word Byte-Reversed Indexed
2105 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2106 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2107 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2108 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2114 STORE(EA, 4, SWAP_4(*rS));
2115 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
2119 # I.3.3.5 Fixed-Point Load and Store Multiple Instrctions
2122 0.46,6.RT,11.RA,16.D:D:::Load Multiple Word
2131 program_interrupt(processor, cia,
2132 illegal_instruction_program_interrupt);
2133 if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT || (EA % 4 != 0))
2134 alignment_interrupt(processor, cia, EA);
2136 GPR(r) = MEM(unsigned, EA, 4);
2141 0.47,6.RS,11.RA,16.D:D:::Store Multiple Word
2148 if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT
2150 alignment_interrupt(processor, cia, EA);
2153 STORE(EA, 4, GPR(r));
2160 # I.3.3.6 Fixed-Point Move Assist Instructions
2163 0.31,6.RT,11.RA,16.NB,21.597,31./:X:::Load String Word Immediate
2169 # if (RA == 0) EA = 0;
2171 # if (NB == 0) n = 32;
2176 # if ((RT + nr >= 32)
2177 # ? (RA >= RT && RA < RT + nr)
2178 # : (RA >= RT || RA < (RT + nr) % 32))
2179 # program_interrupt(processor, cia,
2180 # illegal_instruction_program_interrupt);
2181 # if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
2182 # alignment_interrupt(processor, cia, EA);
2188 # GPR(r) |= INSERTED(MEM(unsigned, EA, 1), i, i+7);
2189 # if (i == 64) i = 32;
2194 0.31,6.RT,11.RA,16.RB,21.533,31./:X:::Load String Word Indexed
2201 # if (RA == 0) b = 0;
2204 # n = EXTRACTED32(XER, 25, 31);
2208 # if (((RT + n >= 32)
2209 # ? ((RA >= RT && RA < RT + n)
2210 # || (RB >= RT && RB < RT + n))
2211 # : ((RA >= RT || RA < (RT + n) % 32)
2212 # || (RB >= RT || RB < (RT + n) % 32)))
2213 # || (RT == RA || RT == RB))
2214 # program_interrupt(processor, cia,
2215 # illegal_instruction_program_interrupt);
2216 # if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
2217 # alignment_interrupt(processor, cia, EA);
2223 # GPR(r) |= INSERTED(MEM(unsigned, EA, 1), i, i+7);
2225 # if (i == 64) i = 32;
2230 0.31,6.RS,11.RA,16.NB,21.725,31./:X:::Store String Word Immedate
2235 # if (RA == 0) EA = 0;
2237 # if (NB == 0) n = 32;
2241 # if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
2242 # alignment_interrupt(processor, cia, EA);
2244 # if (i == 32) r = (r + 1) % 32;
2245 # STORE(EA, 1, EXTRACTED(GPR(r), i, i+7));
2247 # if (i == 64) i = 32;
2252 0.31,6.RS,11.RA,16.RB,21.661,31./:X:::Store String Word Indexed
2258 # if (RA == 0) b = 0;
2261 # if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
2262 # alignment_interrupt(processor, cia, EA);
2263 # n = EXTRACTED32(XER, 25, 31);
2267 # if (i == 32) r = (r + 1) % 32;
2268 # STORE(EA, 1, EXTRACTED(GPR(r), i, i+7));
2270 # if (i == 64) i = 32;
2277 # I.3.3.7 Storage Synchronization Instructions
2279 # HACK: Rather than monitor addresses looking for a reason
2280 # to cancel a reservation. This code instead keeps
2281 # a copy of the data read from memory. Before performing
2282 # a store, the memory area is checked to see if it has
2284 0.31,6.RT,11.RA,16.RB,21.20,31./:X:::Load Word And Reserve Indexed
2285 *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2286 *603: PPC_UNIT_LSU, PPC_UNIT_IU, 1, 2, 0
2287 *603e:PPC_UNIT_LSU, PPC_UNIT_IU, 1, 2, 0
2288 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2295 RESERVE_ADDR = real_addr(EA, 1/*is-read?*/);
2296 RESERVE_DATA = MEM(unsigned, EA, 4);
2298 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
2300 0.31,6.RT,11.RA,16.RB,21.84,31./:X:64::Load Doubleword And Reserve Indexed
2307 RESERVE_ADDR = real_addr(EA, 1/*is-read?*/);
2308 RESERVE_DATA = MEM(unsigned, EA, 8);
2310 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
2312 0.31,6.RS,11.RA,16.RB,21.150,31.1:X:::Store Word Conditional Indexed
2313 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2314 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 8, 8, 0
2315 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 8, 8, 0
2316 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 3, 0
2323 if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/)
2324 && /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 4)) {
2326 CR_SET_XER_SO(0, cr_i_zero);
2329 /* ment to randomly to store, we never do! */
2330 CR_SET_XER_SO(0, 0);
2335 CR_SET_XER_SO(0, 0);
2337 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 1/*Rc*/);
2339 0.31,6.RS,11.RA,16.RB,21.214,31.1:X:64::Store Doubleword Conditional Indexed
2346 if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/)
2347 && /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 8)) {
2349 CR_SET_XER_SO(0, cr_i_zero);
2352 /* ment to randomly to store, we never do */
2353 CR_SET_XER_SO(0, 0);
2358 CR_SET_XER_SO(0, 0);
2360 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 1/*Rc*/);
2362 0.31,6./,11./,16./,21.598,31./:X::sync:Synchronize
2363 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2364 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
2365 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
2366 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
2371 # I.3.3.9 Fixed-Point Arithmetic Instructions
2374 0.14,6.RT,11.RA,16.SI:D:::Add Immediate
2375 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2376 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2377 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2378 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2379 if (RA_is_0) *rT = EXTS(SI);
2380 else *rT = *rA + EXTS(SI);
2381 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rT, (long)*rT));
2382 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
2384 0.15,6.RT,11.RA,16.SI:D:::Add Immediate Shifted
2385 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2386 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2387 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2388 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2389 if (RA_is_0) *rT = EXTS(SI) << 16;
2390 else *rT = *rA + (EXTS(SI) << 16);
2391 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rT, (long)*rT));
2392 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
2394 0.31,6.RT,11.RA,16.RB,21.OE,22.266,31.Rc:XO:::Add
2395 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2396 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2397 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2398 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2401 ALU_END(*rT, 0/*CA*/, OE, Rc);
2402 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2404 0.31,6.RT,11.RA,16.RB,21.OE,22.40,31.Rc:XO:::Subtract From
2405 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2406 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2407 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2408 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2413 ALU_END(*rT, 0/*CA*/, OE, Rc);
2414 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2416 0.12,6.RT,11.RA,16.SI:D:::Add Immediate Carrying
2417 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2418 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2419 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2420 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2423 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
2424 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, 0/*Rc*/);
2426 0.13,6.RT,11.RA,16.SI:D:::Add Immediate Carrying and Record
2427 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2428 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2429 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2430 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2433 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 1/*Rc*/);
2434 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, 1/*Rc*/);
2436 0.8,6.RT,11.RA,16.SI:D:::Subtract From Immediate Carrying
2437 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2438 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2439 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2440 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2445 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
2446 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, 0/*Rc*/);
2448 0.31,6.RT,11.RA,16.RB,21.OE,22.10,31.Rc:XO:::Add Carrying
2449 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2450 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2451 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2452 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2455 ALU_END(*rT, 1/*CA*/, OE, Rc);
2456 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2458 0.31,6.RT,11.RA,16.RB,21.OE,22.8,31.Rc:XO:::Subtract From Carrying
2459 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2460 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2461 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2462 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2463 /* RT <- ~RA + RB + 1 === RT <- RB - RA */
2468 ALU_END(*rT, 1/*CA*/, OE, Rc);
2469 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2471 0.31,6.RT,11.RA,16.RB,21.OE,22.138,31.Rc:XO:::Add Extended
2472 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2473 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2474 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2475 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2479 ALU_END(*rT, 1/*CA*/, OE, Rc);
2480 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2482 0.31,6.RT,11.RA,16.RB,21.OE,22.136,31.Rc:XO:::Subtract From Extended
2483 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2484 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2485 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2486 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2491 ALU_END(*rT, 1/*CA*/, OE, Rc);
2492 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2494 0.31,6.RT,11.RA,16./,21.OE,22.234,31.Rc:XO:::Add to Minus One Extended
2495 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2496 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2497 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2498 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2502 ALU_END(*rT, 1/*CA*/, OE, Rc);
2503 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2505 0.31,6.RT,11.RA,16./,21.OE,22.232,31.Rc:XO:::Subtract From Minus One Extended
2506 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2507 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2508 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2509 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2514 ALU_END(*rT, 1/*CA*/, OE, Rc);
2515 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2517 0.31,6.RT,11.RA,16./,21.OE,22.202,31.Rc:XO::addze:Add to Zero Extended
2518 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2519 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2520 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2521 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2524 ALU_END(*rT, 1/*CA*/, OE, Rc);
2525 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2527 0.31,6.RT,11.RA,16./,21.OE,22.200,31.Rc:XO:::Subtract from Zero Extended
2528 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2529 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2530 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2531 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2535 ALU_END(*rT, 1/*CA*/, OE, Rc);
2536 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2538 0.31,6.RT,11.RA,16./,21.OE,22.104,31.Rc:XO:::Negate
2539 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2540 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2541 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2542 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2546 ALU_END(*rT,0/*CA*/,OE,Rc);
2547 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2549 0.7,6.RT,11.RA,16.SI:D::mulli:Multiply Low Immediate
2550 *601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2551 *603: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
2552 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
2553 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
2554 signed_word prod = *rA * EXTS(SI);
2556 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, 0/*Rc*/);
2558 0.31,6.RT,11.RA,16.RB,21.OE,22.233,31.Rc:D:64::Multiply Low Doubleword
2560 0.31,6.RT,11.RA,16.RB,21.OE,22.235,31.Rc:XO::mullw:Multiply Low Word
2561 *601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2562 *603: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2563 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2564 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0
2565 signed64 a = (signed32)(*rA);
2566 signed64 b = (signed32)(*rB);
2567 signed64 prod = a * b;
2568 signed_word t = prod;
2570 if (t != prod && OE)
2571 XER |= (xer_overflow | xer_summary_overflow);
2572 CR0_COMPARE(t, 0, Rc);
2573 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2575 0.31,6.RT,11.RA,16.RB,21./,22.73,31.Rc:XO:64::Multiply High Doubleword
2577 0.31,6.RT,11.RA,16.RB,21./,22.75,31.Rc:XO::mulhw:Multiply High Word
2578 *601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2579 *603: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2580 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2581 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0
2582 signed64 a = (signed32)(*rA);
2583 signed64 b = (signed32)(*rB);
2584 signed64 prod = a * b;
2585 signed_word t = EXTRACTED64(prod, 0, 31);
2587 CR0_COMPARE(t, 0, Rc);
2588 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2590 0.31,6.RT,11.RA,16.RB,21./,22.9,31.Rc:XO:64::Multiply High Doubleword Unsigned
2592 0.31,6.RT,11.RA,16.RB,21./,22.11,31.Rc:XO::milhwu:Multiply High Word Unsigned
2593 *601: PPC_UNIT_IU, PPC_UNIT_IU, 10, 10, 0
2594 *603: PPC_UNIT_IU, PPC_UNIT_IU, 6, 6, 0
2595 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 6, 6, 0
2596 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0
2597 unsigned64 a = (unsigned32)(*rA);
2598 unsigned64 b = (unsigned32)(*rB);
2599 unsigned64 prod = a * b;
2600 signed_word t = EXTRACTED64(prod, 0, 31);
2602 CR0_COMPARE(t, 0, Rc);
2603 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2605 0.31,6.RT,11.RA,16.RB,21.OE,22.489,31.Rc:XO:64::Divide Doubleword
2607 0.31,6.RT,11.RA,16.RB,21.OE,22.491,31.Rc:XO::divw:Divide Word
2608 *601: PPC_UNIT_IU, PPC_UNIT_IU, 36, 36, 0
2609 *603: PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2610 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2611 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 20, 20, 0
2612 signed64 dividend = (signed32)(*rA);
2613 signed64 divisor = (signed32)(*rB);
2614 if (divisor == 0 /* nb 0x8000..0 is sign extended */
2615 || (dividend == 0x80000000 && divisor == -1)) {
2617 XER |= (xer_overflow | xer_summary_overflow);
2618 CR0_COMPARE(0, 0, Rc);
2621 signed64 quotent = dividend / divisor;
2623 CR0_COMPARE((signed_word)quotent, 0, Rc);
2625 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2627 0.31,6.RT,11.RA,16.RB,21.OE,22.457,31.Rc:XO:64::Divide Doubleword Unsigned
2629 0.31,6.RT,11.RA,16.RB,21.OE,22.459,31.Rc:XO::divwu:Divide Word Unsigned
2630 *601: PPC_UNIT_IU, PPC_UNIT_IU, 36, 36, 0
2631 *603: PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2632 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2633 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 20, 20, 0
2634 unsigned64 dividend = (unsigned32)(*rA);
2635 unsigned64 divisor = (unsigned32)(*rB);
2638 XER |= (xer_overflow | xer_summary_overflow);
2639 CR0_COMPARE(0, 0, Rc);
2642 unsigned64 quotent = dividend / divisor;
2644 CR0_COMPARE((signed_word)quotent, 0, Rc);
2646 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2650 # I.3.3.10 Fixed-Point Compare Instructions
2653 0.11,6.BF,9./,10.L,11.RA,16.SI:D:::Compare Immediate
2654 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2655 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2656 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2657 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2658 if (!is_64bit_mode && L)
2659 program_interrupt(processor, cia,
2660 illegal_instruction_program_interrupt);
2663 signed_word b = EXTS(SI);
2668 CR_COMPARE(BF, a, b);
2670 PPC_INSN_INT_CR(0, RA_BITMASK, BF_BITMASK);
2672 0.31,6.BF,9./,10.L,11.RA,16.RB,21.0,31./:X:::Compare
2673 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2674 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2675 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2676 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2677 if (!is_64bit_mode && L)
2678 program_interrupt(processor, cia,
2679 illegal_instruction_program_interrupt);
2691 CR_COMPARE(BF, a, b);
2693 PPC_INSN_INT_CR(0, RA_BITMASK | RB_BITMASK, BF_BITMASK);
2695 0.10,6.BF,9./,10.L,11.RA,16.UI:D:::Compare Logical Immediate
2696 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2697 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2698 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2699 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2700 if (!is_64bit_mode && L)
2701 program_interrupt(processor, cia,
2702 illegal_instruction_program_interrupt);
2705 unsigned_word b = UI;
2707 a = MASKED(*rA, 32, 63);
2710 CR_COMPARE(BF, a, b);
2712 PPC_INSN_INT_CR(0, RA_BITMASK, BF_BITMASK);
2714 0.31,6.BF,9./,10.L,11.RA,16.RB,21.32,31./:X:::Compare Logical
2715 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2716 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2717 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2718 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2719 if (!is_64bit_mode && L)
2720 program_interrupt(processor, cia,
2721 illegal_instruction_program_interrupt);
2726 a = MASKED(*rA, 32, 63);
2727 b = MASKED(*rB, 32, 63);
2733 CR_COMPARE(BF, a, b);
2735 PPC_INSN_INT_CR(0, RA_BITMASK | RB_BITMASK, BF_BITMASK);
2739 # I.3.3.11 Fixed-Point Trap Instructions
2742 0.2,6.TO,11.RA,16.SI:D:64::Trap Doubleword Immediate
2744 program_interrupt(processor, cia,
2745 illegal_instruction_program_interrupt);
2747 signed_word a = *rA;
2748 signed_word b = EXTS(SI);
2749 if ((a < b && TO{0})
2751 || (a == b && TO{2})
2752 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2753 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2755 program_interrupt(processor, cia,
2756 trap_program_interrupt);
2759 0.3,6.TO,11.RA,16.SI:D:::Trap Word Immediate
2760 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2761 *603: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2762 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2763 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2764 signed_word a = EXTENDED(*rA);
2765 signed_word b = EXTS(SI);
2766 if ((a < b && TO{0})
2768 || (a == b && TO{2})
2769 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2770 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2772 program_interrupt(processor, cia,
2773 trap_program_interrupt);
2775 0.31,6.TO,11.RA,16.RB,21.68,31./:X:64::Trap Doubleword
2777 program_interrupt(processor, cia,
2778 illegal_instruction_program_interrupt);
2780 signed_word a = *rA;
2781 signed_word b = *rB;
2782 if ((a < b && TO{0})
2784 || (a == b && TO{2})
2785 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2786 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2788 program_interrupt(processor, cia,
2789 trap_program_interrupt);
2792 0.31,6.TO,11.RA,16.RB,21.4,31./:X:::Trap Word
2793 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2794 *603: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2795 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2796 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2797 signed_word a = EXTENDED(*rA);
2798 signed_word b = EXTENDED(*rB);
2799 if (TO == 12 && rA == rB) {
2800 ITRACE(trace_breakpoint, ("breakpoint\n"));
2801 cpu_halt(processor, cia, was_trap, 0);
2803 else if ((a < b && TO{0})
2805 || (a == b && TO{2})
2806 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2807 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2809 program_interrupt(processor, cia,
2810 trap_program_interrupt);
2813 # I.3.3.12 Fixed-Point Logical Instructions
2816 0.28,6.RS,11.RA,16.UI:D:::AND Immediate
2817 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2818 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2819 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2820 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2822 CR0_COMPARE(*rA, 0, 1/*Rc*/);
2823 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2824 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 1/*Rc*/);
2826 0.29,6.RS,11.RA,16.UI:D:::AND Immediate Shifted
2827 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2828 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2829 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2830 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2831 *rA = *rS & (UI << 16);
2832 CR0_COMPARE(*rA, 0, 1/*Rc*/);
2833 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2834 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 1/*Rc*/);
2836 0.24,6.RS,11.RA,16.UI:D:::OR Immediate
2837 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2838 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2839 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2840 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2842 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2843 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 0/*Rc*/);
2845 0.25,6.RS,11.RA,16.UI:D:::OR Immediate Shifted
2846 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2847 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2848 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2849 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2850 *rA = *rS | (UI << 16);
2851 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2852 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 0/*Rc*/);
2854 0.26,6.RS,11.RA,16.UI:D:::XOR Immediate
2855 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2856 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2857 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2858 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2860 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2861 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 0/*Rc*/);
2863 0.27,6.RS,11.RA,16.UI:D:::XOR Immediate Shifted
2864 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2865 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2866 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2867 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2868 *rA = *rS ^ (UI << 16);
2869 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2870 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 0/*Rc*/);
2872 0.31,6.RS,11.RA,16.RB,21.28,31.Rc:X:::AND
2873 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2874 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2875 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2876 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2878 CR0_COMPARE(*rA, 0, Rc);
2879 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2880 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2882 0.31,6.RS,11.RA,16.RB,21.444,31.Rc:X:::OR
2883 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2884 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2885 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2886 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2888 CR0_COMPARE(*rA, 0, Rc);
2889 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2890 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2892 0.31,6.RS,11.RA,16.RB,21.316,31.Rc:X:::XOR
2893 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2894 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2895 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2896 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2898 CR0_COMPARE(*rA, 0, Rc);
2899 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2900 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2902 0.31,6.RS,11.RA,16.RB,21.476,31.Rc:X:::NAND
2903 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2904 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2905 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2906 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2908 CR0_COMPARE(*rA, 0, Rc);
2909 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2910 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2912 0.31,6.RS,11.RA,16.RB,21.124,31.Rc:X:::NOR
2913 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2914 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2915 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2916 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2918 CR0_COMPARE(*rA, 0, Rc);
2919 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2920 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2922 0.31,6.RS,11.RA,16.RB,21.284,31.Rc:X:::Equivalent
2923 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2924 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2925 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2926 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2927 *rA = ~(*rS ^ *rB); /* A === B */
2928 CR0_COMPARE(*rA, 0, Rc);
2929 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2930 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2932 0.31,6.RS,11.RA,16.RB,21.60,31.Rc:X:::AND with Complement
2933 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2934 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2935 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2936 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2938 CR0_COMPARE(*rA, 0, Rc);
2939 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2940 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2942 0.31,6.RS,11.RA,16.RB,21.412,31.Rc:X:::OR with Complement
2943 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2944 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2945 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2946 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2948 CR0_COMPARE(*rA, 0, Rc);
2949 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2950 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2952 0.31,6.RS,11.RA,16./,21.954,31.Rc:X::extsb:Extend Sign Byte
2953 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2954 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2955 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2956 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2957 *rA = (signed_word)(signed8)*rS;
2958 CR0_COMPARE(*rA, 0, Rc);
2959 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2960 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
2962 0.31,6.RS,11.RA,16./,21.922,31.Rc:X::extsh:Extend Sign Half Word
2963 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2964 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2965 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2966 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2967 *rA = (signed_word)(signed16)*rS;
2968 CR0_COMPARE(*rA, 0, Rc);
2969 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2970 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
2972 0.31,6.RS,11.RA,16./,21.986,31.Rc:X:64::Extend Sign Word
2973 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2974 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2975 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2976 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2977 # *rA = (signed_word)(signed32)*rS;
2978 # CR0_COMPARE(*rA, 0, Rc);
2980 0.31,6.RS,11.RA,16./,21.58,31.Rc:X:64::Count Leading Zeros Doubleword
2982 # unsigned64 mask = BIT64(0);
2983 # unsigned64 source = *rS;
2984 # while (!(source & mask) && mask != 0) {
2989 # CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */
2991 0.31,6.RS,11.RA,16./,21.26,31.Rc:X:::Count Leading Zeros Word
2992 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2993 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2994 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2995 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2997 unsigned32 mask = BIT32(0);
2998 unsigned32 source = *rS;
2999 while (!(source & mask) && mask != 0) {
3004 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3005 CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */
3009 # I.3.3.13 Fixed-Point Rotate and Shift Instructions
3012 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
3013 # long n = (sh_5 << 4) | sh_0_4;
3014 # unsigned_word r = ROTL64(*rS, n);
3015 # long b = (mb_5 << 4) | mb_0_4;
3016 # unsigned_word m = MASK(b, 63);
3017 # signed_word result = r & m;
3019 # ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3020 # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
3022 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
3023 # long n = (sh_5 << 4) | sh_0_4;
3024 # unsigned_word r = ROTL64(*rS, n);
3025 # long e = (me_5 << 4) | me_0_4;
3026 # unsigned_word m = MASK(0, e);
3027 # signed_word result = r & m;
3029 # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
3031 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
3032 # long n = (sh_5 << 4) | sh_0_4;
3033 # unsigned_word r = ROTL64(*rS, n);
3034 # long b = (mb_5 << 4) | mb_0_4;
3035 # unsigned_word m = MASK(0, (64-n));
3036 # signed_word result = r & m;
3038 # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
3040 0.21,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M:::Rotate Left Word Immediate then AND with Mask
3041 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3042 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3043 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3044 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3047 unsigned32 r = ROTL32(s, n);
3048 unsigned32 m = MASK(MB+32, ME+32);
3049 signed_word result = r & m;
3051 CR0_COMPARE(result, 0, Rc);
3053 ("n=%ld, s=0x%lx, r=0x%lx, m=0x%lx, result=0x%lx, cr=0x%lx\n",
3054 n, (unsigned long)s, (unsigned long)r, (unsigned long)m,
3055 (unsigned long)result, (unsigned long)CR));
3056 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3058 0.30,6.RS,11.RA,16.RB,21.mb,27.8,31.Rc:MDS:64::Rotate Left Doubleword then Clear Left
3059 # long n = MASKED(*rB, 58, 63);
3060 # unsigned_word r = ROTL64(*rS, n);
3061 # long b = (mb_5 << 4) | mb_0_4;
3062 # unsigned_word m = MASK(b, 63);
3063 # signed_word result = r & m;
3065 # CR0_COMPARE(result, 0, Rc);
3067 0.30,6.RS,11.RA,16.RB,21.me,27.9,31.Rc:MDS:64::Rotate Left Doubleword then Clear Right
3068 # long n = MASKED(*rB, 58, 63);
3069 # unsigned_word r = ROTL64(*rS, n);
3070 # long e = (me_5 << 4) | me_0_4;
3071 # unsigned_word m = MASK(0, e);
3072 # signed_word result = r & m;
3074 # CR0_COMPARE(result, 0, Rc);
3076 0.23,6.RS,11.RA,16.RB,21.MB,26.ME,31.Rc:M:::Rotate Left Word then AND with Mask
3077 long n = MASKED(*rB, 59, 63);
3078 unsigned32 r = ROTL32(*rS, n);
3079 unsigned32 m = MASK(MB+32, ME+32);
3080 signed_word result = r & m;
3082 CR0_COMPARE(result, 0, Rc);
3084 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
3085 # long n = (sh_5 << 4) | sh_0_4;
3086 # unsigned_word r = ROTL64(*rS, n);
3087 # long b = (mb_5 << 4) | mb_0_4;
3088 # unsigned_word m = MASK(b, (64-n));
3089 # signed_word result = (r & m) | (*rA & ~m)
3091 # CR0_COMPARE(result, 0, Rc);
3093 0.20,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M::rlwimi:Rotate Left Word Immediate then Mask Insert
3094 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3095 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3096 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3097 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3099 unsigned32 r = ROTL32(*rS, n);
3100 unsigned32 m = MASK(MB+32, ME+32);
3101 signed_word result = (r & m) | (*rA & ~m);
3103 ITRACE(trace_alu, (": n=%ld *rS=0x%lx r=0x%lx m=0x%lx result=0x%lx\n",
3104 n, (unsigned long)*rS, (unsigned long)r, (unsigned long)m,
3105 (unsigned long)result));
3106 CR0_COMPARE(result, 0, Rc);
3107 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3110 0.31,6.RS,11.RA,16.RB,21.27,31.Rc:X:64::Shift Left Doubleword
3112 0.31,6.RS,11.RA,16.RB,21.24,31.Rc:X:::Shift Left Word
3113 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3114 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3115 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3116 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3117 int n = MASKED(*rB, 59, 63);
3118 unsigned32 source = *rS;
3119 signed_word shifted;
3121 shifted = (source << n);
3125 CR0_COMPARE(shifted, 0, Rc);
3127 ("n=%d, source=0x%lx, shifted=0x%lx\n",
3128 n, (unsigned long)source, (unsigned long)shifted));
3129 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3131 0.31,6.RS,11.RA,16.RB,21.539,31.Rc:X:64::Shift Right Doubleword
3133 0.31,6.RS,11.RA,16.RB,21.536,31.Rc:X:::Shift Right Word
3134 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3135 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3136 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3137 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3138 int n = MASKED(*rB, 59, 63);
3139 unsigned32 source = *rS;
3140 signed_word shifted;
3142 shifted = (source >> n);
3146 CR0_COMPARE(shifted, 0, Rc);
3148 ("n=%d, source=0x%lx, shifted=0x%lx\n",
3149 n, (unsigned long)source, (unsigned long)shifted));
3150 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3152 0.31,6.RS,11.RA,16.sh_0_4,21.413,30.sh_5,31.Rc:XS:64::Shift Right Algebraic Doubleword Immediate
3154 0.31,6.RS,11.RA,16.SH,21.824,31.Rc:X:::Shift Right Algebraic Word Immediate
3155 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3156 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3157 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3158 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3160 signed_word r = ROTL32(*rS, /*64*/32-n);
3161 signed_word m = MASK(n+32, 63);
3162 int S = MASKED(*rS, 32, 32);
3163 signed_word shifted = (r & m) | (S ? ~m : 0);
3165 if (S && ((r & ~m) & MASK(32, 63)) != 0)
3169 CR0_COMPARE(shifted, 0, Rc);
3170 ITRACE(trace_alu, (" Result = %ld (0x%lx), XER = %ld\n",
3171 (long)*rA, (long)*rA, (long)XER));
3172 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3174 0.31,6.RS,11.RA,16.RB,21.794,31.Rc:X:64::Shift Right Algebraic Doubleword
3176 0.31,6.RS,11.RA,16.RB,21.792,31.Rc:X:::Shift Right Algebraic Word
3177 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3178 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3179 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3180 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3181 int n = MASKED(*rB, 58, 63);
3182 int shift = (n >= 31 ? 31 : n);
3183 signed32 source = (signed32)*rS; /* signed to keep sign bit */
3184 signed32 shifted = source >> shift;
3185 unsigned32 mask = ((unsigned32)-1) >> (31-shift);
3186 *rA = (signed_word)shifted; /* if 64bit will sign extend */
3187 if (source < 0 && (source & mask))
3191 CR0_COMPARE(shifted, 0, Rc);
3192 ITRACE(trace_alu, (" Result = %ld (0x%lx), XER = %ld\n",
3193 (long)*rA, (long)*rA, (long)XER));
3194 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3197 # I.3.3.14 Move to/from System Register Instructions
3200 0.31,6.RS,11.SPR,21.467,31./:XFX::mtspr %SPR, %RS:Move to Special Purpose Register
3201 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3202 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
3203 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
3204 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
3205 int n = (SPR{5:9} << 5) | SPR{0:4};
3206 if (SPR{0} && IS_PROBLEM_STATE(processor))
3207 program_interrupt(processor, cia,
3208 privileged_instruction_program_interrupt);
3209 else if (!spr_is_valid(n)
3210 || spr_is_readonly(n))
3211 program_interrupt(processor, cia,
3212 illegal_instruction_program_interrupt);
3214 spreg new_val = (spr_length(n) == 64
3216 : MASKED(*rS, 32, 63));
3217 /* HACK - time base registers need to be updated immediatly */
3218 if (WITH_TIME_BASE) {
3221 cpu_set_time_base(processor,
3222 (MASKED64(cpu_get_time_base(processor), 32, 63)
3223 | INSERTED64(new_val, 0, 31)));
3226 cpu_set_time_base(processor,
3227 (MASKED64(cpu_get_time_base(processor), 0, 31)
3228 | INSERTED64(new_val, 32, 63)));
3231 cpu_set_decrementer(processor, new_val);
3242 PPC_INSN_TO_SPR(RS_BITMASK, n);
3244 0.31,6.RT,11.SPR,21.339,31./:XFX::mfspr %RT, %SPR:Move from Special Purpose Register
3245 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3246 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3247 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3248 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
3249 int n = (SPR{5:9} << 5) | SPR{0:4};
3250 if (SPR{0} && IS_PROBLEM_STATE(processor))
3251 program_interrupt(processor, cia,
3252 privileged_instruction_program_interrupt);
3253 else if (!spr_is_valid(n))
3254 program_interrupt(processor, cia,
3255 illegal_instruction_program_interrupt);
3257 /* HACK - time base registers need to be calculated */
3258 if (WITH_TIME_BASE) {
3261 *rT = cpu_get_decrementer(processor);
3265 /* NOTE - these SPR's are not readable. Use mftb[ul] */
3275 PPC_INSN_FROM_SPR(RT_BITMASK, n);
3277 0.31,6.RS,11./,12.FXM,20./,21.144,31./:XFX::mtfcr:Move to Condition Register Fields
3278 *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
3279 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3280 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3281 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
3286 unsigned_word mask = 0;
3288 for (f = 0; f < 8; f++) {
3289 if (FXM & (0x80 >> f))
3290 mask |= (0xf << 4*(7-f));
3292 CR = (MASKED(*rS, 32, 63) & mask) | (CR & ~mask);
3294 PPC_INSN_MTCR(RS_BITMASK, FXM);
3296 0.31,6.BF,9./,11./,16./,21.512,31./:X:::Move to Condition Register from XER
3297 # CR_SET(BF, EXTRACTED32(XER, 0, 3));
3298 # MBLIT32(XER, 0, 3, 0);
3300 0.31,6.RT,11./,16./,21.19,31./:X:::Move From Condition Register
3301 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3302 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3303 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3304 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
3305 *rT = (unsigned32)CR;
3306 PPC_INSN_MFCR(RT_BITMASK);
3309 # I.4.6.2 Floating-Point Load Instructions
3312 0.48,6.FRT,11.RA,16.D:D:f:lfs:Load Floating-Point Single
3313 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3314 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3315 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3316 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3322 *frT = DOUBLE(MEM(unsigned, EA, 4));
3323 PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3325 0.31,6.FRT,11.RA,16.RB,21.535,31./:X:f::Load Floating-Point Single Indexed
3326 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3327 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3328 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3329 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3335 *frT = DOUBLE(MEM(unsigned, EA, 4));
3336 PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3338 0.49,6.FRT,11.RA,16.D:D:f::Load Floating-Point Single with Update
3339 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3340 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3341 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3342 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3345 program_interrupt(processor, cia,
3346 illegal_instruction_program_interrupt);
3348 *frT = DOUBLE(MEM(unsigned, EA, 4));
3350 PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3352 0.31,6.FRT,11.RA,16.RB,21.576,31./:X:f::Load Floating-Point Single with Update Indexed
3353 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3354 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3355 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3356 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3359 program_interrupt(processor, cia,
3360 illegal_instruction_program_interrupt);
3362 *frT = DOUBLE(MEM(unsigned, EA, 4));
3364 PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3366 0.50,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double
3367 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3368 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3369 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3370 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3376 *frT = MEM(unsigned, EA, 8);
3377 PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3379 0.31,6.FRT,11.RA,16.RB,21.599,31./:X:f::Load Floating-Point Double Indexed
3380 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3381 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3382 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3383 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3389 *frT = MEM(unsigned, EA, 8);
3390 PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3392 0.51,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double with Update
3393 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3394 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3395 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3396 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3399 program_interrupt(processor, cia,
3400 illegal_instruction_program_interrupt);
3402 *frT = MEM(unsigned, EA, 8);
3404 PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3406 0.31,6.FRT,11.RA,16.RB,21.631,31./:X:f::Load Floating-Point Double with Update Indexed
3407 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3408 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3409 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3410 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3413 program_interrupt(processor, cia,
3414 illegal_instruction_program_interrupt);
3416 *frT = MEM(unsigned, EA, 8);
3418 PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3422 # I.4.6.3 Floating-Point Store Instructions
3425 0.52,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single
3426 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3427 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3428 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3429 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3435 STORE(EA, 4, SINGLE(*frS));
3436 PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3438 0.31,6.FRS,11.RA,16.RB,21.663,31./:X:f::Store Floating-Point Single Indexed
3439 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3440 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3441 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3442 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3448 STORE(EA, 4, SINGLE(*frS));
3449 PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3451 0.53,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single with Update
3452 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3453 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3454 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3455 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3458 program_interrupt(processor, cia,
3459 illegal_instruction_program_interrupt);
3461 STORE(EA, 4, SINGLE(*frS));
3463 PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3465 0.31,6.FRS,11.RA,16.RB,21.695,31./:X:f::Store Floating-Point Single with Update Indexed
3466 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3467 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3468 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3469 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3472 program_interrupt(processor, cia,
3473 illegal_instruction_program_interrupt);
3475 STORE(EA, 4, SINGLE(*frS));
3477 PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3479 0.54,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double
3480 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3481 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3482 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3483 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3490 PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3492 0.31,6.FRS,11.RA,16.RB,21.727,31./:X:f::Store Floating-Point Double Indexed
3493 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3494 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3495 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3496 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3503 PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3505 0.55,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double with Update
3506 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3507 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3508 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3509 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3512 program_interrupt(processor, cia,
3513 illegal_instruction_program_interrupt);
3517 PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3519 0.31,6.FRS,11.RA,16.RB,21.759,31./:X:f::Store Floating-Point Double with Update Indexed
3520 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3521 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3522 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3523 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3526 program_interrupt(processor, cia,
3527 illegal_instruction_program_interrupt);
3531 PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3535 # I.4.6.4 Floating-Point Move Instructions
3538 0.63,6.FRT,11./,16.FRB,21.72,31.Rc:X:f::Floating Move Register
3539 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3540 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3541 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3542 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3545 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3547 0.63,6.FRT,11./,16.FRB,21.40,31.Rc:X:f::Floating Negate
3548 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3549 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3550 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3551 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3552 *frT = *frB ^ BIT64(0);
3554 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3556 0.63,6.FRT,11./,16.FRB,21.264,31.Rc:X:f::Floating Absolute Value
3557 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3558 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3559 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3560 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3561 *frT = *frB & ~BIT64(0);
3563 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3565 0.63,6.FRT,11./,16.FRB,21.136,31.Rc:X:f::Floating Negative Absolute Value
3566 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3567 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3568 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3569 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3570 *frT = *frB | BIT64(0);
3572 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3576 # I.4.6.5 Floating-Point Arithmetic Instructions
3579 0.63,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadd:Floating Add
3580 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3581 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3582 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3583 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3585 if (is_invalid_operation(processor, cia,
3587 fpscr_vxsnan | fpscr_vxisi,
3590 invalid_arithemetic_operation(processor, cia,
3592 0, /*instruction_is_frsp*/
3593 0, /*instruction_is_convert_to_64bit*/
3594 0, /*instruction_is_convert_to_32bit*/
3595 0); /*single-precision*/
3599 double s = *(double*)frA + *(double*)frB;
3603 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3605 0.59,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadds:Floating Add Single
3606 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3607 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3608 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3609 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3611 if (is_invalid_operation(processor, cia,
3613 fpscr_vxsnan | fpscr_vxisi,
3616 invalid_arithemetic_operation(processor, cia,
3618 0, /*instruction_is_frsp*/
3619 0, /*instruction_is_convert_to_64bit*/
3620 0, /*instruction_is_convert_to_32bit*/
3621 1); /*single-precision*/
3625 float s = *(double*)frA + *(double*)frB;
3629 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3631 0.63,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsub:Floating Subtract
3632 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3633 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3634 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3635 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3637 if (is_invalid_operation(processor, cia,
3639 fpscr_vxsnan | fpscr_vxisi,
3642 invalid_arithemetic_operation(processor, cia,
3644 0, /*instruction_is_frsp*/
3645 0, /*instruction_is_convert_to_64bit*/
3646 0, /*instruction_is_convert_to_32bit*/
3647 0); /*single-precision*/
3651 double s = *(double*)frA - *(double*)frB;
3655 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3657 0.59,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsubs:Floating Subtract Single
3658 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3659 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3660 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3661 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3663 if (is_invalid_operation(processor, cia,
3665 fpscr_vxsnan | fpscr_vxisi,
3668 invalid_arithemetic_operation(processor, cia,
3670 0, /*instruction_is_frsp*/
3671 0, /*instruction_is_convert_to_64bit*/
3672 0, /*instruction_is_convert_to_32bit*/
3673 1); /*single-precision*/
3677 float s = *(double*)frA - *(double*)frB;
3681 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3683 0.63,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmul:Floating Multiply
3684 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3685 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3686 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3687 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3689 if (is_invalid_operation(processor, cia,
3691 fpscr_vxsnan | fpscr_vximz,
3694 invalid_arithemetic_operation(processor, cia,
3696 0, /*instruction_is_frsp*/
3697 0, /*instruction_is_convert_to_64bit*/
3698 0, /*instruction_is_convert_to_32bit*/
3699 0); /*single-precision*/
3703 double s = *(double*)frA * *(double*)frC;
3707 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRC_BITMASK, Rc);
3709 0.59,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmuls:Floating Multiply Single
3710 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3711 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3712 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3713 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3715 if (is_invalid_operation(processor, cia,
3717 fpscr_vxsnan | fpscr_vximz,
3720 invalid_arithemetic_operation(processor, cia,
3722 0, /*instruction_is_frsp*/
3723 0, /*instruction_is_convert_to_64bit*/
3724 0, /*instruction_is_convert_to_32bit*/
3725 1); /*single-precision*/
3729 float s = *(double*)frA * *(double*)frC;
3733 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRC_BITMASK, Rc);
3735 0.63,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdiv:Floating Divide
3736 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 31, 31, 0
3737 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 33, 33, 0
3738 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 33, 33, 0
3739 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 32, 32, 0
3741 if (is_invalid_operation(processor, cia,
3743 fpscr_vxsnan | fpscr_vxzdz,
3746 invalid_arithemetic_operation(processor, cia,
3748 0, /*instruction_is_frsp*/
3749 0, /*instruction_is_convert_to_64bit*/
3750 0, /*instruction_is_convert_to_32bit*/
3751 0); /*single-precision*/
3755 double s = *(double*)frA / *(double*)frB;
3759 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3761 0.59,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdivs:Floating Divide Single
3762 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 17, 17, 0
3763 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0
3764 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0
3765 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0
3767 if (is_invalid_operation(processor, cia,
3769 fpscr_vxsnan | fpscr_vxzdz,
3772 invalid_arithemetic_operation(processor, cia,
3774 0, /*instruction_is_frsp*/
3775 0, /*instruction_is_convert_to_64bit*/
3776 0, /*instruction_is_convert_to_32bit*/
3777 1); /*single-precision*/
3781 float s = *(double*)frA / *(double*)frB;
3785 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3787 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f:fmadd:Floating Multiply-Add
3788 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3789 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3790 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3791 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3793 double product; /*HACK! - incorrectly loosing precision ... */
3794 /* compute the multiply */
3795 if (is_invalid_operation(processor, cia,
3797 fpscr_vxsnan | fpscr_vximz,
3800 invalid_arithemetic_operation(processor, cia,
3801 (unsigned64*)&product, *frA, 0, *frC,
3802 0, /*instruction_is_frsp*/
3803 0, /*instruction_is_convert_to_64bit*/
3804 0, /*instruction_is_convert_to_32bit*/
3805 0); /*single-precision*/
3809 product = *(double*)frA * *(double*)frC;
3811 /* compute the add */
3812 if (is_invalid_operation(processor, cia,
3814 fpscr_vxsnan | fpscr_vxisi,
3817 invalid_arithemetic_operation(processor, cia,
3818 frT, product, *frB, 0,
3819 0, /*instruction_is_frsp*/
3820 0, /*instruction_is_convert_to_64bit*/
3821 0, /*instruction_is_convert_to_32bit*/
3822 0); /*single-precision*/
3826 double s = product + *(double*)frB;
3830 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
3832 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f::Floating Multiply-Add Single
3833 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3834 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3835 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3836 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3838 float product; /*HACK! - incorrectly loosing precision ... */
3839 /* compute the multiply */
3840 if (is_invalid_operation(processor, cia,
3842 fpscr_vxsnan | fpscr_vximz,
3845 invalid_arithemetic_operation(processor, cia,
3846 (unsigned64*)&product, *frA, 0, *frC,
3847 0, /*instruction_is_frsp*/
3848 0, /*instruction_is_convert_to_64bit*/
3849 0, /*instruction_is_convert_to_32bit*/
3850 0); /*single-precision*/
3854 product = *(double*)frA * *(double*)frC;
3856 /* compute the add */
3857 if (is_invalid_operation(processor, cia,
3859 fpscr_vxsnan | fpscr_vxisi,
3862 invalid_arithemetic_operation(processor, cia,
3863 frT, product, *frB, 0,
3864 0, /*instruction_is_frsp*/
3865 0, /*instruction_is_convert_to_64bit*/
3866 0, /*instruction_is_convert_to_32bit*/
3867 0); /*single-precision*/
3871 float s = product + *(double*)frB;
3872 *(double*)frT = (double)s;
3875 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
3877 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract
3878 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3879 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3880 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3881 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3883 double product; /*HACK! - incorrectly loosing precision ... */
3884 /* compute the multiply */
3885 if (is_invalid_operation(processor, cia,
3887 fpscr_vxsnan | fpscr_vximz,
3890 invalid_arithemetic_operation(processor, cia,
3891 (unsigned64*)&product, *frA, 0, *frC,
3892 0, /*instruction_is_frsp*/
3893 0, /*instruction_is_convert_to_64bit*/
3894 0, /*instruction_is_convert_to_32bit*/
3895 0); /*single-precision*/
3899 product = *(double*)frA * *(double*)frC;
3901 /* compute the subtract */
3902 if (is_invalid_operation(processor, cia,
3904 fpscr_vxsnan | fpscr_vxisi,
3907 invalid_arithemetic_operation(processor, cia,
3908 frT, product, *frB, 0,
3909 0, /*instruction_is_frsp*/
3910 0, /*instruction_is_convert_to_64bit*/
3911 0, /*instruction_is_convert_to_32bit*/
3912 0); /*single-precision*/
3916 double s = product - *(double*)frB;
3920 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
3922 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract Single
3923 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3924 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3925 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3926 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3928 float product; /*HACK! - incorrectly loosing precision ... */
3929 /* compute the multiply */
3930 if (is_invalid_operation(processor, cia,
3932 fpscr_vxsnan | fpscr_vximz,
3935 invalid_arithemetic_operation(processor, cia,
3936 (unsigned64*)&product, *frA, 0, *frC,
3937 0, /*instruction_is_frsp*/
3938 0, /*instruction_is_convert_to_64bit*/
3939 0, /*instruction_is_convert_to_32bit*/
3940 0); /*single-precision*/
3944 product = *(double*)frA * *(double*)frC;
3946 /* compute the subtract */
3947 if (is_invalid_operation(processor, cia,
3949 fpscr_vxsnan | fpscr_vxisi,
3952 invalid_arithemetic_operation(processor, cia,
3953 frT, product, *frB, 0,
3954 0, /*instruction_is_frsp*/
3955 0, /*instruction_is_convert_to_64bit*/
3956 0, /*instruction_is_convert_to_32bit*/
3957 0); /*single-precision*/
3961 float s = product - *(double*)frB;
3962 *(double*)frT = (double)s;
3965 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
3967 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add
3968 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3969 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3970 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3971 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3973 double product; /*HACK! - incorrectly loosing precision ... */
3974 /* compute the multiply */
3975 if (is_invalid_operation(processor, cia,
3977 fpscr_vxsnan | fpscr_vximz,
3980 invalid_arithemetic_operation(processor, cia,
3981 (unsigned64*)&product, *frA, 0, *frC,
3982 0, /*instruction_is_frsp*/
3983 0, /*instruction_is_convert_to_64bit*/
3984 0, /*instruction_is_convert_to_32bit*/
3985 0); /*single-precision*/
3989 product = *(double*)frA * *(double*)frC;
3991 /* compute the add */
3992 if (is_invalid_operation(processor, cia,
3994 fpscr_vxsnan | fpscr_vxisi,
3997 invalid_arithemetic_operation(processor, cia,
3998 frT, product, *frB, 0,
3999 0, /*instruction_is_frsp*/
4000 0, /*instruction_is_convert_to_64bit*/
4001 0, /*instruction_is_convert_to_32bit*/
4002 0); /*single-precision*/
4006 double s = -(product + *(double*)frB);
4010 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4012 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add Single
4013 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4014 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4015 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4016 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4018 float product; /*HACK! - incorrectly loosing precision ... */
4019 /* compute the multiply */
4020 if (is_invalid_operation(processor, cia,
4022 fpscr_vxsnan | fpscr_vximz,
4025 invalid_arithemetic_operation(processor, cia,
4026 (unsigned64*)&product, *frA, 0, *frC,
4027 0, /*instruction_is_frsp*/
4028 0, /*instruction_is_convert_to_64bit*/
4029 0, /*instruction_is_convert_to_32bit*/
4030 0); /*single-precision*/
4034 product = *(double*)frA * *(double*)frC;
4036 /* compute the add */
4037 if (is_invalid_operation(processor, cia,
4039 fpscr_vxsnan | fpscr_vxisi,
4042 invalid_arithemetic_operation(processor, cia,
4043 frT, product, *frB, 0,
4044 0, /*instruction_is_frsp*/
4045 0, /*instruction_is_convert_to_64bit*/
4046 0, /*instruction_is_convert_to_32bit*/
4047 0); /*single-precision*/
4051 float s = -(product + *(double*)frB);
4052 *(double*)frT = (double)s;
4055 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4057 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract
4058 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
4059 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
4060 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
4061 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4063 double product; /*HACK! - incorrectly loosing precision ... */
4064 /* compute the multiply */
4065 if (is_invalid_operation(processor, cia,
4067 fpscr_vxsnan | fpscr_vximz,
4070 invalid_arithemetic_operation(processor, cia,
4071 (unsigned64*)&product, *frA, 0, *frC,
4072 0, /*instruction_is_frsp*/
4073 0, /*instruction_is_convert_to_64bit*/
4074 0, /*instruction_is_convert_to_32bit*/
4075 0); /*single-precision*/
4079 product = *(double*)frA * *(double*)frC;
4081 /* compute the subtract */
4082 if (is_invalid_operation(processor, cia,
4084 fpscr_vxsnan | fpscr_vxisi,
4087 invalid_arithemetic_operation(processor, cia,
4088 frT, product, *frB, 0,
4089 0, /*instruction_is_frsp*/
4090 0, /*instruction_is_convert_to_64bit*/
4091 0, /*instruction_is_convert_to_32bit*/
4092 0); /*single-precision*/
4096 double s = -(product - *(double*)frB);
4100 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4102 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract Single
4103 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4104 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4105 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4106 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4108 float product; /*HACK! - incorrectly loosing precision ... */
4109 /* compute the multiply */
4110 if (is_invalid_operation(processor, cia,
4112 fpscr_vxsnan | fpscr_vximz,
4115 invalid_arithemetic_operation(processor, cia,
4116 (unsigned64*)&product, *frA, 0, *frC,
4117 0, /*instruction_is_frsp*/
4118 0, /*instruction_is_convert_to_64bit*/
4119 0, /*instruction_is_convert_to_32bit*/
4120 0); /*single-precision*/
4124 product = *(double*)frA * *(double*)frC;
4126 /* compute the subtract */
4127 if (is_invalid_operation(processor, cia,
4129 fpscr_vxsnan | fpscr_vxisi,
4132 invalid_arithemetic_operation(processor, cia,
4133 frT, product, *frB, 0,
4134 0, /*instruction_is_frsp*/
4135 0, /*instruction_is_convert_to_64bit*/
4136 0, /*instruction_is_convert_to_32bit*/
4137 0); /*single-precision*/
4141 float s = -(product - *(double*)frB);
4142 *(double*)frT = (double)s;
4145 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4149 # I.4.6.6 Floating-Point Rounding and Conversion Instructions
4152 0.63,6.FRT,11./,16.FRB,21.12,31.Rc:X:f::Floating Round to Single-Precision
4153 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4154 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4155 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4156 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4159 unsigned64 frac_grx;
4161 /* split off cases for what to do */
4162 if (EXTRACTED64(*frB, 1, 11) < 897
4163 && EXTRACTED64(*frB, 1, 63) > 0) {
4164 if ((FPSCR & fpscr_ue) == 0) GOTO(Disabled_Exponent_Underflow);
4165 if ((FPSCR & fpscr_ue) != 0) GOTO(Enabled_Exponent_Underflow);
4167 if (EXTRACTED64(*frB, 1, 11) > 1150
4168 && EXTRACTED64(*frB, 1, 11) < 2047) {
4169 if ((FPSCR & fpscr_oe) == 0) GOTO(Disabled_Exponent_Overflow);
4170 if ((FPSCR & fpscr_oe) != 0) GOTO(Enabled_Exponent_Overflow);
4172 if (EXTRACTED64(*frB, 1, 11) > 896
4173 && EXTRACTED64(*frB, 1, 11) < 1151) GOTO(Normal_Operand);
4174 if (EXTRACTED64(*frB, 1, 63) == 0) GOTO(Zero_Operand);
4175 if (EXTRACTED64(*frB, 1, 11) == 2047) {
4176 if (EXTRACTED64(*frB, 12, 63) == 0) GOTO(Infinity_Operand);
4177 if (EXTRACTED64(*frB, 12, 12) == 1) GOTO(QNaN_Operand);
4178 if (EXTRACTED64(*frB, 12, 12) == 0
4179 && EXTRACTED64(*frB, 13, 63) > 0) GOTO(SNaN_Operand);
4182 LABEL(Disabled_Exponent_Underflow):
4183 sign = EXTRACTED64(*frB, 0, 0);
4184 if (EXTRACTED64(*frB, 1, 11) == 0) {
4186 frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4188 if (EXTRACTED64(*frB, 1, 11) > 0) {
4189 exp = EXTRACTED64(*frB, 1, 11) - 1023;
4190 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4192 /* G|R|X == zero from above */
4193 while (exp < -126) {
4195 frac_grx = (INSERTED64(EXTRACTED64(frac_grx, 0, 54), 1, 55)
4196 | MASKED64(frac_grx, 55, 55));
4198 FPSCR_SET_UX(EXTRACTED64(frac_grx, 24, 55) > 0);
4199 Round_Single(processor, sign, &exp, &frac_grx);
4200 FPSCR_SET_XX(FPSCR & fpscr_fi);
4201 if (EXTRACTED64(frac_grx, 0, 52) == 0) {
4202 *frT = INSERTED64(sign, 0, 0);
4203 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
4204 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
4206 if (EXTRACTED64(frac_grx, 0, 52) > 0) {
4207 if (EXTRACTED64(frac_grx, 0, 0) == 1) {
4208 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4209 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4211 if (EXTRACTED64(frac_grx, 0, 0) == 0) {
4212 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_denormalized_number);
4213 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_denormalized_number);
4215 /*Normalize_Operand:*/
4216 while (EXTRACTED64(frac_grx, 0, 0) == 0) {
4218 frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1, 52), 0, 51);
4220 *frT = (INSERTED64(sign, 0, 0)
4221 | INSERTED64(exp + 1023, 1, 11)
4222 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4226 LABEL(Enabled_Exponent_Underflow):
4228 sign = EXTRACTED64(*frB, 0, 0);
4229 if (EXTRACTED64(*frB, 1, 11) == 0) {
4231 frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4233 if (EXTRACTED64(*frB, 1, 11) > 0) {
4234 exp = EXTRACTED64(*frB, 1, 11) - 1023;
4235 frac_grx = (BIT64(0) |
4236 INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52));
4238 /*Normalize_Operand:*/
4239 while (EXTRACTED64(frac_grx, 0, 0) == 0) {
4241 frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1, 52), 0, 51);
4243 Round_Single(processor, sign, &exp, &frac_grx);
4244 FPSCR_SET_XX(FPSCR & fpscr_fi);
4246 *frT = (INSERTED64(sign, 0, 0)
4247 | INSERTED64(exp + 1023, 1, 11)
4248 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4249 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4250 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4253 LABEL(Disabled_Exponent_Overflow):
4255 if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
4256 if (EXTRACTED64(*frB, 0, 0) == 0) {
4257 *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
4258 FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
4260 if (EXTRACTED64(*frB, 0, 0) == 1) {
4261 *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
4262 FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
4265 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_zero) {
4266 if (EXTRACTED64(*frB, 0, 0) == 0) {
4267 *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
4268 FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4270 if (EXTRACTED64(*frB, 0, 0) == 1) {
4271 *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
4272 FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4275 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_pos_infinity) {
4276 if (EXTRACTED64(*frB, 0, 0) == 0) {
4277 *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
4278 FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
4280 if (EXTRACTED64(*frB, 0, 0) == 1) {
4281 *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
4282 FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4285 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_neg_infinity) {
4286 if (EXTRACTED64(*frB, 0, 0) == 0) {
4287 *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
4288 FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4290 if (EXTRACTED64(*frB, 0, 0) == 1) {
4291 *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
4292 FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
4295 /* FPSCR[FR] <- undefined */
4300 LABEL(Enabled_Exponent_Overflow):
4301 sign = EXTRACTED64(*frB, 0, 0);
4302 exp = EXTRACTED64(*frB, 1, 11) - 1023;
4303 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4304 Round_Single(processor, sign, &exp, &frac_grx);
4305 FPSCR_SET_XX(FPSCR & fpscr_fi);
4307 LABEL(Enabled_Overflow):
4310 *frT = (INSERTED64(sign, 0, 0)
4311 | INSERTED64(exp + 1023, 1, 11)
4312 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4313 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4314 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4317 LABEL(Zero_Operand):
4319 if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
4320 if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
4325 LABEL(Infinity_Operand):
4327 if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
4328 if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
4333 LABEL(QNaN_Operand):
4334 *frT = INSERTED64(EXTRACTED64(*frB, 0, 34), 0, 34);
4335 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
4340 LABEL(SNaN_Operand):
4341 FPSCR_OR_VX(fpscr_vxsnan);
4342 if ((FPSCR & fpscr_ve) == 0) {
4343 *frT = (MASKED64(*frB, 0, 11)
4345 | MASKED64(*frB, 13, 34));
4346 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
4352 LABEL(Normal_Operand):
4353 sign = EXTRACTED64(*frB, 0, 0);
4354 exp = EXTRACTED64(*frB, 1, 11) - 1023;
4355 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4356 Round_Single(processor, sign, &exp, &frac_grx);
4357 FPSCR_SET_XX(FPSCR & fpscr_fi);
4358 if (exp > 127 && (FPSCR & fpscr_oe) == 0) GOTO(Disabled_Exponent_Overflow);
4359 if (exp > 127 && (FPSCR & fpscr_oe) != 0) GOTO(Enabled_Overflow);
4360 *frT = (INSERTED64(sign, 0, 0)
4361 | INSERTED64(exp + 1023, 1, 11)
4362 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4363 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4364 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4368 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
4371 0.63,6.FRT,11./,16.FRB,21.814,31.Rc:X:64,f::Floating Convert To Integer Doubleword
4372 floating_point_assist_interrupt(processor, cia);
4374 0.63,6.FRT,11./,16.FRB,21.815,31.Rc:X:64,f::Floating Convert To Integer Doubleword with round towards Zero
4375 floating_point_assist_interrupt(processor, cia);
4377 0.63,6.FRT,11./,16.FRB,21.14,31.Rc:X:f::Floating Convert To Integer Word
4378 floating_point_assist_interrupt(processor, cia);
4380 0.63,6.FRT,11./,16.FRB,21.15,31.Rc:X:f:fctiwz:Floating Convert To Integer Word with round towards Zero
4381 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4382 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4383 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4384 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4386 convert_to_integer(processor, cia,
4388 fpscr_rn_round_towards_zero, 32);
4390 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
4392 0.63,6.FRT,11./,16.FRB,21.846,31.Rc:X:64,f::Floating Convert from Integer Doubleword
4393 int sign = EXTRACTED64(*frB, 0, 0);
4395 unsigned64 frac = *frB;
4397 if (frac == 0) GOTO(Zero_Operand);
4398 if (sign == 1) frac = ~frac + 1;
4399 while (EXTRACTED64(frac, 0, 0) == 0) {
4400 /*??? do the loop 0 times if (FRB) = max negative integer */
4401 frac = INSERTED64(EXTRACTED64(frac, 1, 63), 0, 62);
4404 Round_Float(processor, sign, &exp, &frac, FPSCR & fpscr_rn);
4405 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4406 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4407 *frT = (INSERTED64(sign, 0, 0)
4408 | INSERTED64(exp + 1023, 1, 11)
4409 | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
4412 LABEL(Zero_Operand):
4415 FPSCR_SET_FPRF(fpscr_rf_pos_zero);
4420 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
4424 # I.4.6.7 Floating-Point Compare Instructions
4427 0.63,6.BF,9./,11.FRA,16.FRB,21.0,31./:X:f:fcmpu:Floating Compare Unordered
4428 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4429 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4430 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4431 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4434 if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
4435 c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
4436 else if (is_less_than(frA, frB))
4437 c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
4438 else if (is_greater_than(frA, frB))
4439 c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
4441 c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
4443 CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
4444 if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0))
4445 FPSCR_OR_VX(fpscr_vxsnan);
4447 PPC_INSN_FLOAT_CR(0, FRA_BITMASK | FRB_BITMASK, BF_BITMASK);
4449 0.63,6.BF,9./,11.FRA,16.FRB,21.32,31./:X:f:fcmpo:Floating Compare Ordered
4450 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4451 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4452 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4453 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4456 if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
4457 c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
4458 else if (is_less_than(frA, frB))
4459 c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
4460 else if (is_greater_than(frA, frB))
4461 c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
4463 c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
4465 CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
4466 if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0)) {
4467 FPSCR_OR_VX(fpscr_vxsnan);
4468 if ((FPSCR & fpscr_ve) == 0)
4469 FPSCR_OR_VX(fpscr_vxvc);
4471 else if (is_QNaN(*frA, 0) || is_QNaN(*frB, 0)) {
4472 FPSCR_OR_VX(fpscr_vxvc);
4475 PPC_INSN_FLOAT_CR(0, FRA_BITMASK | FRB_BITMASK, BF_BITMASK);
4479 # I.4.6.8 Floating-Point Status and Control Register Instructions
4482 0.63,6.FRT,11./,16./,21.583,31.Rc:X:f::Move From FPSCR
4483 floating_point_assist_interrupt(processor, cia);
4488 0.63,6.BF,9./,11.BFA,14./,16./,21.64,31./:X:f::Move to Condition Register from FPSCR
4489 floating_point_assist_interrupt(processor, cia);
4491 # unsigned field = FPSCR_FIELD(BFA);
4492 # CR_SET(BF, field);
4495 # FPSCR &= ~(fpscr_fx | fpscr_ox);
4498 # FPSCR &= ~(fpscr_ux | fpscr_zx | fpscr_xx | fpscr_vxsnan);
4501 # FPSCR &= ~(fpscr_vxisi | fpscr_vxidi | fpscr_vxzdz | fpscr_vximz);
4504 # FPSCR &= ~(fpscr_vxvc);
4507 # FPSCR &= ~(fpscr_vxsoft | fpscr_vxsqrt | fpscr_vxcvi);
4512 0.64,6.BF,9./,11./,16.U,20./,21.134,31.Rc:X:f::Move To FPSCR Field Immediate
4513 floating_point_assist_interrupt(processor, cia);
4516 # /* FIXME - what about the effect this has on exception bits */
4519 0.63,6./,7.FLM,15./,16.FRB,21.711,31.Rc:XFL:f::Move To FPSCR Fields
4522 for (i = 0; i < 8; i++) {
4523 if ((FLM & BIT8(i))) {
4524 FPSCR &= ~MASK32(i*4, i*4+3);
4525 FPSCR |= MASKED32(*frB, i*4, i*4+3);
4530 0.63,6.BT,11./,16./,21.70,31.Rc:X:f::Move To FPSCR Bit 0
4531 floating_point_assist_interrupt(processor, cia);
4533 # unsigned32 mask = ~BIT32(BT) | (fpscr_fex | fpscr_vx);
4535 # /* FIXME - what about the effect this has on exception bits */
4538 0.63,6.BT,11./,16./,21.38,31.Rc:X:f::Move To FPSCR Bit 1
4539 floating_point_assist_interrupt(processor, cia);
4541 # unsigned32 bit = BIT32(BT) & ~(fpscr_fex | fpscr_vx);
4543 # /* FIXME - need to take care of when and why FX is set */
4544 # /* FIXME - if FX (or another exception bit is set) shall
4545 # an exception occure */
4546 # /* FPSCR |= fpscr_fx; */
4547 # /* FIXME - what about the effect this has on exception bits */
4552 # I.A.1.1 Floating-Point Store Instruction
4554 0.31,6.FRS,11.RA,16.RB,21.983,31./:X:f,o::Store Floating-Point as Integer Word Indexed
4555 program_interrupt(processor, cia, optional_instruction_program_interrupt);
4558 # I.A.1.2 Floating-Point Arithmetic Instructions
4561 0.63,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f,o::Floating Square Root
4562 program_interrupt(processor, cia, optional_instruction_program_interrupt);
4564 0.59,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f,o::Floating Square Root Single
4565 program_interrupt(processor, cia, optional_instruction_program_interrupt);
4567 0.59,6.FRT,11./,16.FRB,21./,26.24,31.Rc:A:f,o::Floating Reciprocal Estimate Single
4568 program_interrupt(processor, cia, optional_instruction_program_interrupt);
4570 0.63,6.FRT,11./,16.FRB,21./,26.26,31.Rc:A:f,o::Floating Reciprocal Square Root Estimate
4571 program_interrupt(processor, cia, optional_instruction_program_interrupt);
4574 # I.A.1.3 Floating-Point Select Instruction
4577 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.23,31.Rc:A:f,o::Floating Select
4578 *601: PPC_UNIT_BAD, PPC_UNIT_BAD, 0, 0, 0
4579 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4580 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4581 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4582 if (CURRENT_MODEL == MODEL_ppc601) {
4583 program_interrupt(processor, cia, optional_instruction_program_interrupt);
4585 unsigned64 zero = 0;
4587 if (is_NaN(*frA, 0) || is_less_than (frA, &zero)) *frT = *frB;
4590 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4594 # II.3.2 Cache Management Instructions
4597 0.31,6./,11.RA,16.RB,21.982,31./:X::icbi:Instruction Cache Block Invalidate
4598 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4599 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4600 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4601 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
4602 /* blindly flush all instruction cache entries */
4603 #if WITH_IDECODE_CACHE_SIZE
4604 cpu_flush_icache(processor);
4606 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0);
4608 0.19,6./,11./,16./,21.150,31./:XL::isync:Instruction Synchronize
4609 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4610 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4611 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4612 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
4613 cpu_synchronize_context(processor, cia);
4614 PPC_INSN_INT(0, 0, 0);
4618 # II.3.2.2 Data Cache Instructions
4621 0.31,6./,11.RA,16.RB,21.278,31./:X:::Data Cache Block Touch
4622 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4623 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4624 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4625 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
4626 TRACE(trace_tbd,("Data Cache Block Touch\n"));
4627 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4629 0.31,6./,11.RA,16.RB,21.246,31./:X:::Data Cache Block Touch for Store
4630 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4631 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4632 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4633 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4634 TRACE(trace_tbd,("Data Cache Block Touch for Store\n"));
4635 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4637 0.31,6./,11.RA,16.RB,21.1014,31./:X:::Data Cache Block set to Zero
4638 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4639 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 10, 10, 0
4640 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 10, 10, 0
4641 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4642 TRACE(trace_tbd,("Data Cache Block set to Zero\n"));
4643 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4645 0.31,6./,11.RA,16.RB,21.54,31./:X:::Data Cache Block Store
4646 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4647 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
4648 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
4649 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
4650 TRACE(trace_tbd,("Data Cache Block Store\n"));
4651 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4653 0.31,6./,11.RA,16.RB,21.86,31./:X:::Data Cache Block Flush
4654 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4655 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
4656 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
4657 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
4658 TRACE(trace_tbd,("Data Cache Block Flush\n"));
4659 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4662 # II.3.3 Enforce In-order Execution of I/O Instruction
4665 0.31,6./,11./,16./,21.854,31./:X::eieio:Enforce In-order Execution of I/O
4666 /* Since this model has no instruction overlap
4667 this instruction need do nothing */
4670 # II.4.1 Time Base Instructions
4673 0.31,6.RT,11.tbr,21.371,31./:XFX::mftb:Move From Time Base
4674 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
4675 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
4676 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
4677 int n = (tbr{5:9} << 5) | tbr{0:4};
4679 if (is_64bit_implementation) *rT = TB;
4680 else *rT = EXTRACTED64(TB, 32, 63);
4682 else if (n == 269) {
4683 if (is_64bit_implementation) *rT = EXTRACTED64(TB, 0, 31);
4684 else *rT = EXTRACTED64(TB, 0, 31);
4687 program_interrupt(processor, cia,
4688 illegal_instruction_program_interrupt);
4692 # III.2.3.1 System Linkage Instructions
4695 0.19,6./,11./,16./,21.50,31./:XL::rfi:Return From Interrupt
4696 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4697 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4698 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4699 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
4700 if (IS_PROBLEM_STATE(processor)) {
4701 program_interrupt(processor, cia,
4702 privileged_instruction_program_interrupt);
4705 MSR = (MASKED(SRR1, 0, 32)
4706 | MASKED(SRR1, 37, 41)
4707 | MASKED(SRR1, 48, 63));
4708 NIA = MASKED(SRR0, 0, 61);
4709 cpu_synchronize_context(processor, cia);
4710 check_masked_interrupts(processor);
4714 # III.3.4.1 Move to/from System Register Instructions
4717 #0.31,6.RS,11.SPR,21.467,31./:XFX:::Move To Special Purpose Register
4718 #0.31,6.RT,11.SPR,21.339,31./:XFX:::Move From Special Purpose Register
4719 0.31,6.RS,11./,16./,21.146,31./:X:::Move To Machine State Register
4720 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4721 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4722 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4723 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4724 if (IS_PROBLEM_STATE(processor))
4725 program_interrupt(processor, cia,
4726 privileged_instruction_program_interrupt);
4729 check_masked_interrupts(processor);
4732 0.31,6.RT,11./,16./,21.83,31./:X:::Move From Machine State Register
4733 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4734 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
4735 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
4736 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
4737 if (IS_PROBLEM_STATE(processor))
4738 program_interrupt(processor, cia,
4739 privileged_instruction_program_interrupt);
4742 check_masked_interrupts(processor);
4747 # III.4.11.1 Cache Management Instructions
4750 0.31,6./,11.RA,16.RB,21.470,31./:X::dcbi:Data Cache Block Invalidate
4751 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4752 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4753 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4754 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4755 if (IS_PROBLEM_STATE(processor))
4756 program_interrupt(processor, cia,
4757 privileged_instruction_program_interrupt);
4759 TRACE(trace_tbd,("Data Cache Block Invalidate\n"));
4762 # III.4.11.2 Segment Register Manipulation Instructions
4765 0.31,6.RS,11./,12.SR,16./,21.210,31./:X:32:mtsr %SR,%RS:Move To Segment Register
4766 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4767 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4768 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4769 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4770 if (IS_PROBLEM_STATE(processor))
4771 program_interrupt(processor, cia,
4772 privileged_instruction_program_interrupt);
4776 0.31,6.RS,11./,16.RB,21.242,31./:X:32:mtsrin %RS,%RB:Move To Segment Register Indirect
4777 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4778 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4779 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4780 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4781 if (IS_PROBLEM_STATE(processor))
4782 program_interrupt(processor, cia,
4783 privileged_instruction_program_interrupt);
4785 SEGREG(EXTRACTED32(*rB, 0, 3)) = *rS;
4787 0.31,6.RT,11./,12.SR,16./,21.595,31./:X:32:mfsr %RT,%RS:Move From Segment Register
4788 *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
4789 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4790 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4791 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4792 if (IS_PROBLEM_STATE(processor))
4793 program_interrupt(processor, cia,
4794 privileged_instruction_program_interrupt);
4798 0.31,6.RT,11./,16.RB,21.659,31./:X:32:mfsrin %RT,%RB:Move From Segment Register Indirect
4799 *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
4800 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4801 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4802 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4803 if (IS_PROBLEM_STATE(processor))
4804 program_interrupt(processor, cia,
4805 privileged_instruction_program_interrupt);
4807 *rT = SEGREG(EXTRACTED32(*rB, 0, 3));
4811 # III.4.11.3 Lookaside Buffer Management Instructions (Optional)
4814 0.31,6./,11./,16.RB,21.434,31./:X:64::SLB Invalidate Entry
4816 0.31,6./,11./,16./,21.498,31./:X:64::SLB Invalidate All
4818 0.31,6./,11./,16.RB,21.306,31./:X:::TLB Invalidate Entry
4819 if (IS_PROBLEM_STATE(processor))
4820 program_interrupt(processor, cia,
4821 privileged_instruction_program_interrupt);
4826 proc = psim_cpu(cpu_system(processor), nr);
4827 if (proc == NULL) break;
4828 cpu_page_tlb_invalidate_entry(proc, *rB);
4833 0.31,6./,11./,16./,21.370,31./:X:::TLB Invalidate All
4834 if (IS_PROBLEM_STATE(processor))
4835 program_interrupt(processor, cia,
4836 privileged_instruction_program_interrupt);
4841 proc = psim_cpu(cpu_system(processor), nr);
4842 if (proc == NULL) break;
4843 cpu_page_tlb_invalidate_all(proc);
4848 0.31,6./,11./,16./,21.566,31./:X:::TLB Synchronize
4849 /* nothing happens here - always in sync */
4852 # III.A.1.2 External Access Instructions
4855 0.31,6.RT,11.RA,16.RB,21.310,31./:X:earwax::External Control In Word Indexed
4857 0.31,6.RS,11.RA,16.RB,21.438,31./:X:earwax::External Control Out Word Indexed