]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/ppc/ppc-instructions
Initial creation of sourceware repository
[thirdparty/binutils-gdb.git] / sim / ppc / ppc-instructions
1 #
2 # This file is part of the program psim.
3 #
4 # Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
5 #
6 # --
7 #
8 # The pseudo-code that appears below, translated into C, was copied
9 # by Andrew Cagney of Moss Vale, Australia.
10 #
11 # This pseudo-code is copied by permission from the publication
12 # "The PowerPC Architecture: A Specification for A New Family of
13 # RISC Processors" (ISBN 1-55860-316-6) copyright 1993, 1994 by
14 # International Business Machines Corporation.
15 #
16 # THIS PERMISSION IS PROVIDED WITHOUT WARRANTY OF ANY KIND, EITHER
17 # EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES
18 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 #
20 # --
21 #
22 # This program is free software; you can redistribute it and/or modify
23 # it under the terms of the GNU General Public License as published by
24 # the Free Software Foundation; either version 2 of the License, or
25 # (at your option) any later version.
26 #
27 # This program is distributed in the hope that it will be useful,
28 # but WITHOUT ANY WARRANTY; without even the implied warranty of
29 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 # GNU General Public License for more details.
31 #
32 # You should have received a copy of the GNU General Public License
33 # along with this program; if not, write to the Free Software
34 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
35 #
36 \f
37 # PowerPC models
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
42
43 # Flags for model.h
44 ::model-macro:::
45 #define PPC_INSN_INT(OUT_MASK, IN_MASK, RC) \
46 do { \
47 if (CURRENT_MODEL_ISSUE > 0) { \
48 if (RC) \
49 ppc_insn_int_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, 1 << 0); \
50 else \
51 ppc_insn_int(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK); \
52 } \
53 } while (0)
54
55 #define PPC_INSN_INT_CR(OUT_MASK, IN_MASK, CR_MASK) \
56 do { \
57 if (CURRENT_MODEL_ISSUE > 0) \
58 ppc_insn_int_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, CR_MASK); \
59 } while (0)
60
61 #define PPC_INSN_CR(OUT_MASK, IN_MASK) \
62 do { \
63 if (CURRENT_MODEL_ISSUE > 0) \
64 ppc_insn_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK); \
65 } while (0)
66
67 #define PPC_INSN_FLOAT(OUT_MASK, IN_MASK, RC) \
68 do { \
69 if (CURRENT_MODEL_ISSUE > 0) { \
70 if (RC) \
71 ppc_insn_float(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK); \
72 else \
73 ppc_insn_float_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, 1 << 0); \
74 } \
75 } while (0)
76
77 #define PPC_INSN_FLOAT_CR(OUT_MASK, IN_MASK, CR_MASK) \
78 do { \
79 if (CURRENT_MODEL_ISSUE > 0) \
80 ppc_insn_float_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, CR_MASK); \
81 } while (0)
82
83 #define PPC_INSN_INT_FLOAT(OUT_INT_MASK, OUT_FP_MASK, IN_INT_MASK, IN_FP_MASK) \
84 do { \
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); \
87 } while (0)
88
89 #define PPC_INSN_FROM_SPR(INT_MASK, SPR) \
90 do { \
91 if (CURRENT_MODEL_ISSUE > 0) \
92 ppc_insn_from_spr(MY_INDEX, cpu_model(processor), INT_MASK, SPR); \
93 } while (0)
94
95 #define PPC_INSN_TO_SPR(INT_MASK, SPR) \
96 do { \
97 if (CURRENT_MODEL_ISSUE > 0) \
98 ppc_insn_to_spr(MY_INDEX, cpu_model(processor), INT_MASK, SPR); \
99 } while (0)
100
101 #define PPC_INSN_MFCR(INT_MASK) \
102 do { \
103 if (CURRENT_MODEL_ISSUE > 0) \
104 ppc_insn_mfcr(MY_INDEX, cpu_model(processor), INT_MASK); \
105 } while (0)
106
107 #define PPC_INSN_MTCR(INT_MASK, FXM) \
108 do { \
109 if (CURRENT_MODEL_ISSUE > 0) \
110 ppc_insn_mtcr(MY_INDEX, cpu_model(processor), INT_MASK, FXM); \
111 } while (0)
112
113 ::model-data:::
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
125 } ppc_function_unit;
126
127 /* Structure to hold timing information on a per instruction basis */
128 struct _model_time {
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 */
134 };
135
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 */
139
140 #define PPC_NO_SPR (-1) /* flag for no SPR register */
141
142 /* Return if 1 bit set */
143 #define PPC_ONE_BIT_SET_P(x) (((x) & ((x)-1)) == 0)
144
145 /* Structure for each functional unit that is busy */
146 typedef struct _model_busy model_busy;
147 struct _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 */
157 };
158
159 /* Structure to hold the current state information for the simulated CPU model */
160 struct _model_data {
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 */
185 };
186
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",
197 };
198
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)",
232 };
233
234 static const char *const ppc_nr_mtcrf_crs[9] = {
235 "mtcrf moving 0 CRs",
236 "mtcrf moving 1 CR",
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",
244 };
245 \f
246 # Trace releasing resources
247 void::model-static::model_trace_release:model_data *model_ptr, model_busy *busy
248 int i;
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));
255 }
256 }
257 }
258 if (busy->fp_busy) {
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));
262 }
263 }
264 }
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));
269 }
270 }
271 if (busy->cr_fpscr_busy & 0x100)
272 TRACE(trace_model, ("Register fpscr is now available.\n"));
273 }
274 if (busy->spr_busy != PPC_NO_SPR)
275 TRACE(trace_model, ("Register %s is now available.\n", spr_name(busy->spr_busy)));
276
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
279 int i;
280 if (int_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));
284 }
285 }
286 }
287 if (fp_mask) {
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));
291 }
292 }
293 }
294 if (cr_mask) {
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));
298 }
299 }
300 }
301
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
304 int i;
305 if (int_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));
310 }
311 }
312 }
313 if (fp_busy) {
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));
318 }
319 }
320 }
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));
326 }
327 }
328 if (cr_or_fpscr_busy & 0x100)
329 TRACE(trace_model, ("Waiting for register fpscr.\n"));
330 }
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)));
333 \f
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;
340 model_busy *next;
341
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;
354
355 if (WITH_TRACE && ppc_trace[trace_model])
356 model_trace_release(model_ptr, cur_busy);
357
358 model_ptr->busy[cur_busy->unit] = 0;
359 cur_busy->next = free_list;
360 free_list = cur_busy;
361 }
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;
371 }
372 }
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;
378 }
379 else {
380 TRACE(trace_model,("%s still working, issue = %d, done = %d\n",
381 ppc_function_unit_name[cur_busy->unit],
382 cur_busy->issue,
383 cur_busy->done));
384 busy_tail->next = cur_busy;
385 busy_tail = cur_busy;
386 }
387 }
388
389 busy_tail->next = (model_busy *)0;
390 model_ptr->busy_tail = busy_tail;
391 model_ptr->free_list = free_list;
392
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
395 model_busy *busy;
396
397 TRACE(trace_model,("unit = %s, issue = %d, done = %d\n", ppc_function_unit_name[unit], issue, done));
398
399 if (!model_ptr->free_list) {
400 busy = ZALLOC(model_busy);
401 }
402 else {
403 busy = model_ptr->free_list;
404 model_ptr->free_list = busy->next;
405 busy->next = (model_busy *)0;
406 busy->int_busy = 0;
407 busy->fp_busy = 0;
408 busy->cr_fpscr_busy = 0;
409 busy->nr_writebacks = 0;
410 }
411
412 busy->unit = unit;
413 busy->issue = issue;
414 busy->done = done;
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]++;
420 return busy;
421 \f
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;
427
428 for (;;) {
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);
433
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);
438
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 */
441 stall_increment = 1;
442 model_new_cycle(model_ptr);
443 }
444
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);
451 }
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);
456
457 # Wait for a CR to become unbusy
458 void::model-function::model_wait_for_cr:model_data *model_ptr, unsigned CRBIT
459 unsigned u;
460 unsigned32 cr_mask;
461 int cr_var = 0;
462 for (u = 0xc0000000; (u != 0) && (CRBIT & u) == 0; u >>= 4 )
463 cr_var++;
464
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);
470 }
471
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;
476
477 if ((model_ptr->int_busy & int_mask) != 0) {
478 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
479
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);
483
484 model_ptr->nr_stalls_data++;
485 model_new_cycle(model_ptr);
486 }
487 }
488
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;
492 if (out_mask)
493 busy_ptr->nr_writebacks = (PPC_ONE_BIT_SET_P(out_mask)) ? 1 : 2;
494
495 if (WITH_TRACE && ppc_trace[trace_model])
496 model_trace_make_busy(model_ptr, out_mask, 0, 0);
497
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;
502
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 */
505
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);
509
510 model_ptr->nr_stalls_data++;
511 model_new_cycle(model_ptr);
512 }
513 }
514
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;
520 if (out_mask)
521 busy_ptr->nr_writebacks = (PPC_ONE_BIT_SET_P(out_mask)) ? 1 : 2;
522
523 if (cr_mask)
524 busy_ptr->nr_writebacks++;
525
526 if (WITH_TRACE && ppc_trace[trace_model])
527 model_trace_make_busy(model_ptr, out_mask, 0, cr_mask);
528
529
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;
534
535 if ((model_ptr->cr_fpscr_busy & cr_mask) != 0) {
536 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
537
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);
541
542 model_ptr->nr_stalls_data++;
543 model_new_cycle(model_ptr);
544 }
545 }
546
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;
550 if (out_mask)
551 busy_ptr->nr_writebacks = 1;
552
553 if (WITH_TRACE && ppc_trace[trace_model])
554 model_trace_make_busy(model_ptr, 0, 0, out_mask);
555
556
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;
561
562 if ((model_ptr->fp_busy & fp_mask) != 0) {
563 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
564
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);
568
569 model_ptr->nr_stalls_data++;
570 model_new_cycle(model_ptr);
571 }
572 }
573
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);
580
581
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;
586
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 */
589
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);
593
594 model_ptr->nr_stalls_data++;
595 model_new_cycle(model_ptr);
596 }
597 }
598
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);
607
608
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;
614
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 */
617
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);
621
622 model_ptr->nr_stalls_data++;
623 model_new_cycle(model_ptr);
624 }
625
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);
634 return;
635 }
636
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;
640
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);
644
645 model_ptr->nr_stalls_data++;
646 model_new_cycle(model_ptr);
647 }
648
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);
655
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;
659
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);
663
664 model_ptr->nr_stalls_data++;
665 model_new_cycle(model_ptr);
666 }
667
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)));
673
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;
678
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);
682
683 model_ptr->nr_stalls_data++;
684 model_new_cycle(model_ptr);
685 }
686
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);
693
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
696 int f;
697 int nr_crs = 0;
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;
702
703 for (f = 0; f < 8; f++) {
704 if (FXM & (0x80 >> f)) {
705 cr_mask |= (1 << f);
706 nr_crs++;
707 }
708 }
709
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);
713
714 model_ptr->nr_stalls_data++;
715 model_new_cycle(model_ptr);
716 }
717
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;
721 }
722
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);
730 \f
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);
744 }
745 return model_ptr;
746
747 void::model-function::model_init:model_data *model_ptr
748
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);
753
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);
759
760 unsigned_word::model-function::model_get_number_of_cycles:model_data *model_ptr
761 return (model_ptr->nr_cycles);
762
763 model_print *::model-function::model_mon_info:model_data *model_ptr
764 model_print *head;
765 model_print *tail;
766 ppc_function_unit i;
767 count_type nr_insns;
768 int j;
769
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 = "";
775
776 if (model_ptr->nr_stalls_data) {
777 tail->next = ZALLOC(model_print);
778 tail = tail->next;
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";
783 }
784
785 if (model_ptr->nr_stalls_unit) {
786 tail->next = ZALLOC(model_print);
787 tail = tail->next;
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";
792 }
793
794 if (model_ptr->nr_stalls_serialize) {
795 tail->next = ZALLOC(model_print);
796 tail = tail->next;
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";
801 }
802
803 if (model_ptr->nr_stalls_writeback) {
804 tail->next = ZALLOC(model_print);
805 tail = tail->next;
806 tail->count = model_ptr->nr_stalls_writeback;
807 tail->name = "";
808 tail->suffix_plural = "times a write-back slot was unavailable";
809 tail->suffix_singular = "time a writeback was unavailable";
810 }
811
812 if (model_ptr->nr_branches) {
813 tail->next = ZALLOC(model_print);
814 tail = tail->next;
815 tail->count = model_ptr->nr_branches;
816 tail->name = "branch";
817 tail->suffix_plural = "es";
818 tail->suffix_singular = "";
819 }
820
821 if (model_ptr->nr_branches_fallthrough) {
822 tail->next = ZALLOC(model_print);
823 tail = tail->next;
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";
828 }
829
830 if (model_ptr->nr_branch_predict_trues) {
831 tail->next = ZALLOC(model_print);
832 tail = tail->next;
833 tail->count = model_ptr->nr_branch_predict_trues;
834 tail->name = "successful branch prediction";
835 tail->suffix_plural = "s";
836 tail->suffix_singular = "";
837 }
838
839 if (model_ptr->nr_branch_predict_falses) {
840 tail->next = ZALLOC(model_print);
841 tail = tail->next;
842 tail->count = model_ptr->nr_branch_predict_falses;
843 tail->name = "unsuccessful branch prediction";
844 tail->suffix_plural = "s";
845 tail->suffix_singular = "";
846 }
847
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);
851 tail = tail->next;
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";
856 }
857 }
858
859 for (j = 0; j < 9; j++) {
860 if (model_ptr->nr_mtcrf_crs[j]) {
861 tail->next = ZALLOC(model_print);
862 tail = tail->next;
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";
867 }
868 }
869
870 nr_insns = 0;
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);
875 tail = tail->next;
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 = "";
880 }
881 }
882
883 tail->next = ZALLOC(model_print);
884 tail = tail->next;
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";
889
890 tail->next = (model_print *)0;
891 return head;
892
893 void::model-function::model_mon_info_free:model_data *model_ptr, model_print *ptr
894 while (ptr) {
895 model_print *next = ptr->next;
896 free((void *)ptr);
897 ptr = next;
898 }
899
900 void::model-function::model_branches:model_data *model_ptr, int failed, int conditional
901 model_ptr->nr_units[PPC_UNIT_BPU]++;
902 if (failed)
903 model_ptr->nr_branches_fallthrough++;
904 else
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 */
909
910 void::model-function::model_branch_predict:model_data *model_ptr, int success
911 if (success)
912 model_ptr->nr_branch_predict_trues++;
913 else
914 model_ptr->nr_branch_predict_falses++;
915
916 \f
917 # The following (illegal) instruction is `known' by gen and is
918 # called when ever an illegal instruction is encountered
919 ::internal::illegal
920 program_interrupt(processor, cia,
921 illegal_instruction_program_interrupt);
922
923
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);
929
930
931 #
932 # Floating point support functions
933 #
934
935 # Convert 32bit single to 64bit double
936 unsigned64::function::DOUBLE:unsigned32 WORD
937 unsigned64 FRT;
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)));
947 }
948 else if (EXTRACTED32(WORD, 1, 8) == 0
949 && EXTRACTED32(WORD, 9, 31) != 0) {
950 /* denormalized operand */
951 int sign = EXTRACTED32(WORD, 0, 0);
952 int exp = -126;
953 unsigned64 frac = INSERTED64(EXTRACTED32(WORD, 9, 31), 1, (52 - 29));
954 /* normalize the operand */
955 while (MASKED64(frac, 0, 0) == 0) {
956 frac <<= 1;
957 exp -= 1;
958 }
959 FRT = (INSERTED64(sign, 0, 0)
960 | INSERTED64(exp + 1023, 1, 11)
961 | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
962 }
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)));
970 }
971 else {
972 error("DOUBLE - unknown case\n");
973 FRT = 0;
974 }
975 return FRT;
976
977 # Convert 64bit single to 32bit double
978 unsigned32::function::SINGLE:unsigned64 FRS
979 unsigned32 WORD;
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));
985 }
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 */
994 while (exp < -126) {
995 frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63);
996 exp += 1;
997 }
998 WORD = (INSERTED32(sign, 0, 0)
999 | INSERTED32(0x00, 1, 8)
1000 | INSERTED32(EXTRACTED64(frac, 1, 23), 9, 31));
1001 }
1002 else {
1003 WORD = 0x0; /* ??? */
1004 }
1005 return WORD;
1006
1007
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 */
1011 unsigned64 out;
1012 int inc = 0;
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;
1021 }
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;
1026 }
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;
1031 }
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));
1038 *exp = *exp + 1;
1039 }
1040 /* frac_grx[24:52] = 0 already */
1041 FPSCR_SET_FR(inc);
1042 FPSCR_SET_FI(gbit || rbit || xbit);
1043
1044
1045 #
1046 void::function::Round_Integer:cpu *processor, int sign, unsigned64 *frac, int *frac64, int gbit, int rbit, int xbit, fpscreg round_mode
1047 int inc = 0;
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;
1052 }
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;
1057 }
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;
1062 }
1063 /* frac[0:64] = frac[0:64} + inc */
1064 *frac += (*frac64 && inc ? 1 : 0);
1065 *frac64 = (*frac64 + inc) & 0x1;
1066 FPSCR_SET_FR(inc);
1067 FPSCR_SET_FI(gbit | rbit | xbit);
1068
1069
1070 void::function::Round_Float:cpu *processor, int sign, int *exp, unsigned64 *frac, fpscreg round_mode
1071 int carry_out;
1072 int inc = 0;
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;
1081 }
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;
1086 }
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;
1091 }
1092 /* frac//carry_out = frac + inc */
1093 *frac = (*frac >> 1) + (INSERTED64(inc, 52, 52) >> 1);
1094 carry_out = EXTRACTED64(*frac, 0, 0);
1095 *frac <<= 1;
1096 if (carry_out == 1) *exp = *exp + 1;
1097 FPSCR_SET_FR(inc);
1098 FPSCR_SET_FI(gbit | rbit | xbit);
1099 FPSCR_SET_XX(FPSCR & fpscr_fi);
1100
1101
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
1104 int i;
1105 int exp = 0;
1106 unsigned64 frac = 0;
1107 int frac64 = 0;
1108 int gbit = 0;
1109 int rbit = 0;
1110 int xbit = 0;
1111 int sign = EXTRACTED64(frb, 0, 0);
1112 /***/
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)
1116 GOTO(SNaN_Operand);
1117 if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 1)
1118 GOTO(QNaN_Operand);
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);
1124 frac64 = 0;
1125 }
1126 if (EXTRACTED64(frb, 1, 11) == 0) { /* denorm */
1127 frac = INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
1128 frac64 = 0;
1129 }
1130 gbit = 0, rbit = 0, xbit = 0;
1131 for (i = 1; i <= 63 - exp; i++) {
1132 xbit = rbit | xbit;
1133 rbit = gbit;
1134 gbit = frac64;
1135 frac64 = EXTRACTED64(frac, 63, 63);
1136 frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63);
1137 }
1138 Round_Integer(processor, sign, &frac, &frac64, gbit, rbit, xbit, round_mode);
1139 if (sign == 1) { /* frac[0:64] = ~frac[0:64] + 1 */
1140 frac = ~frac;
1141 frac64 ^= 1;
1142 frac += (frac64 ? 1 : 0);
1143 frac64 = (frac64 + 1) & 0x1;
1144 }
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 */
1163 GOTO(Done);
1164 /**/
1165 LABEL(Infinity_Operand):
1166 FPSCR_SET_FR(0);
1167 FPSCR_SET_FI(0);
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;
1173 }
1174 else {
1175 if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/
1176 if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
1177 }
1178 /* FPSCR[FPRF] = undefined */
1179 }
1180 GOTO(Done);
1181 /**/
1182 LABEL(SNaN_Operand):
1183 FPSCR_SET_FR(0);
1184 FPSCR_SET_FI(0);
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 */
1190 }
1191 GOTO(Done);
1192 /**/
1193 LABEL(QNaN_Operand):
1194 FPSCR_SET_FR(0);
1195 FPSCR_SET_FI(0);
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 */
1201 }
1202 GOTO(Done);
1203 /**/
1204 LABEL(Large_Operand):
1205 FPSCR_SET_FR(0);
1206 FPSCR_SET_FI(0);
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;
1212 }
1213 else {
1214 if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/
1215 if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
1216 }
1217 /* FPSCR[fprf] = undefined */
1218 }
1219 /**/
1220 LABEL(Done):
1221
1222
1223 # extract out raw fields of a FP number
1224 int::function::sign:unsigned64 FRS
1225 return (MASKED64(FRS, 0, 0)
1226 ? -1
1227 : 1);
1228 int::function::biased_exp:unsigned64 frs, int single
1229 if (single)
1230 return EXTRACTED64(frs, 1, 8);
1231 else
1232 return EXTRACTED64(frs, 1, 11);
1233 unsigned64::function::fraction:unsigned64 frs, int single
1234 if (single)
1235 return EXTRACTED64(frs, 9, 31);
1236 else
1237 return EXTRACTED64(frs, 12, 63);
1238
1239 # a number?, each of the below return +1 or -1 (based on sign bit)
1240 # if true.
1241 int::function::is_nor:unsigned64 frs, int single
1242 int exp = biased_exp(frs, single);
1243 return (exp >= 1
1244 && exp <= (single ? 254 : 2046));
1245 int::function::is_zero:unsigned64 FRS
1246 return (MASKED64(FRS, 1, 63) == 0
1247 ? sign(FRS)
1248 : 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
1253 ? sign(frs)
1254 : 0);
1255 int::function::is_inf:unsigned64 frs, int single
1256 int exp = biased_exp(frs, single);
1257 unsigned64 frac = fraction(frs, single);
1258 return (exp == (single ? 255 : 2047) && frac == 0
1259 ? sign(frs)
1260 : 0);
1261 int::function::is_NaN:unsigned64 frs, int single
1262 int exp = biased_exp(frs, single);
1263 unsigned64 frac = fraction(frs, single);
1264 return (exp == (single ? 255 : 2047) && frac != 0
1265 ? sign(frs)
1266 : 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)))
1270 ? sign(frs)
1271 : 0);
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;
1280
1281
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
1284 unsigned64 frt = 0;
1285 if (is_NaN(fra, single))
1286 frt = fra;
1287 else if (is_NaN(frb, single))
1288 if (instruction_is_frsp)
1289 frt = MASKED64(frb, 0, 34);
1290 else
1291 frt = frb;
1292 else if (is_NaN(frc, single))
1293 frt = frc;
1294 else if (generate_qnan)
1295 frt = MASK64(1, 12); /* 0x7FF8_0000_0000_0000 */
1296 else
1297 error("select_qnan - default reached\n");
1298 return frt;
1299
1300
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
1303 int fail = 0;
1304 if ((check & fpscr_vxsnan)
1305 && (is_SNaN(fra, single) || is_SNaN(frb, single))) {
1306 FPSCR_OR_VX(fpscr_vxsnan);
1307 fail = 1;
1308 }
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);
1315 fail = 1;
1316 }
1317 if ((check & fpscr_vxidi)
1318 && (is_inf(fra, single) && is_inf(frb, single))) {
1319 FPSCR_OR_VX(fpscr_vxidi);
1320 fail = 1;
1321 }
1322 if ((check & fpscr_vxzdz)
1323 && (is_zero(fra) && is_zero(frb))) {
1324 FPSCR_OR_VX(fpscr_vxzdz);
1325 fail = 1;
1326 }
1327 if ((check & fpscr_vximz)
1328 && (is_zero(fra) && is_inf(frb, single))) {
1329 FPSCR_OR_VX(fpscr_vximz);
1330 fail = 1;
1331 }
1332 if ((check & fpscr_vxvc)
1333 && (is_NaN(fra, single) || is_NaN(frb, single))) {
1334 FPSCR_OR_VX(fpscr_vxvc);
1335 fail = 1;
1336 }
1337 if ((check & fpscr_vxsoft)) {
1338 FPSCR_OR_VX(fpscr_vxsoft);
1339 fail = 1;
1340 }
1341 if ((check & fpscr_vxsqrt)
1342 && sign(fra) < 0) {
1343 FPSCR_OR_VX(fpscr_vxsqrt);
1344 fail = 1;
1345 }
1346 /* if ((check && fpscr_vxcvi) {
1347 && (is_inf(fra, single) || is_NaN(fra, single) || is_large(fra, single)))
1348 FPSCR_OR_VX(fpscr_vxcvi);
1349 fail = 1;
1350 }
1351 */
1352 return fail;
1353
1354
1355
1356
1357
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 */
1362 /* FRT unchaged */
1363 FPSCR_SET_FR(0);
1364 FPSCR_SET_FI(0);
1365 /* fpscr_FPRF unchanged */
1366 }
1367 else {
1368 /* invalid operation exception disabled */
1369 if (instruction_is_convert_to_64bit) {
1370 error("oopsi");
1371 }
1372 else if (instruction_is_convert_to_32bit) {
1373 error("oopsi");
1374 }
1375 else { /* arrith, frsp */
1376 *frt = select_qnan(fra, frb, frc,
1377 instruction_is_frsp, 1/*generate*/, single);
1378 FPSCR_SET_FR(0);
1379 FPSCR_SET_FI(0);
1380 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
1381 }
1382 }
1383
1384
1385
1386
1387 # detect divide by zero
1388 int::function::is_invalid_zero_divide:cpu *processor, unsigned_word cia, unsigned64 fra, unsigned64 frb, int single
1389 int fail = 0;
1390 if (is_zero (frb)) {
1391 FPSCR_SET_ZX (1);
1392 fail = 1;
1393 }
1394 return fail;
1395
1396
1397
1398
1399 # handle case of invalid operation
1400 void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, unsigned64 *frt, unsigned64 fra, unsigned64 frb, int single
1401 if (FPSCR & fpscr_ze) {
1402 /* zero-divide exception enabled */
1403 /* FRT unchaged */
1404 FPSCR_SET_FR(0);
1405 FPSCR_SET_FI(0);
1406 /* fpscr_FPRF unchanged */
1407 }
1408 else {
1409 /* zero-divide exception disabled */
1410 FPSCR_SET_FR(0);
1411 FPSCR_SET_FI(0);
1412 if ((sign (fra) < 0 && sign (frb) < 0)
1413 || (sign (fra) > 0 && sign (frb) > 0)) {
1414 *frt = MASK64 (1, 11); /* 0 : 2047 : 0..0 */
1415 FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
1416 }
1417 else {
1418 *frt = MASK64 (0, 11); /* 1 : 2047 : 0..0 */
1419 FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
1420 }
1421 }
1422
1423
1424
1425
1426
1427 #
1428 # 0.0.0.0 Illegal instruction used for kernel mode emulation
1429 #
1430 0.0,6./,11./,16./,21./,31.1:X:::instruction_call
1431 if (!os_emul_instruction_call(processor, cia, real_addr(cia, 1)))
1432 program_interrupt(processor, cia,
1433 illegal_instruction_program_interrupt);
1434
1435 #
1436 # I.2.4.1 Branch Instructions
1437 #
1438 0.18,6.LI,30.AA,31.LK:I:::Branch
1439 *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1440 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1441 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1442 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1443 /* WITH_OPTION_MPC860C0
1444 No problem here because this branch is predicted taken (unconditional). */
1445 if (AA) NIA = IEA(EXTS(LI_0b00));
1446 else NIA = IEA(CIA + EXTS(LI_0b00));
1447 if (LK) LR = (spreg)CIA+4;
1448 if (CURRENT_MODEL_ISSUE > 0)
1449 model_branches(cpu_model(processor), 1, -1);
1450
1451 0.16,6.BO,11.BI,16.BD,30.AA,31.LK:B:::Branch Conditional
1452 *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1453 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1454 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1455 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1456 int M, ctr_ok, cond_ok, succeed;
1457 if (CURRENT_MODEL_ISSUE > 0 && ! BO{0})
1458 model_wait_for_cr(cpu_model(processor), BIT32_BI);
1459 if (is_64bit_implementation && is_64bit_mode) M = 0;
1460 else M = 32;
1461 if (!BO{2}) CTR = CTR - 1;
1462 ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != (BO{3}));
1463 cond_ok = BO{0} || ((CR{BI}) == (BO{1}));
1464 if (ctr_ok && cond_ok) {
1465 if (AA) NIA = IEA(EXTS(BD_0b00));
1466 else NIA = IEA(CIA + EXTS(BD_0b00));
1467 succeed = 1;
1468 }
1469 else
1470 succeed = 0;
1471 if (LK) LR = (spreg)IEA(CIA + 4);
1472 #ifdef WITH_OPTION_MPC860C0
1473 if (option_mpc860c0 && (BO{0} && BO{2} || !BO{4})) {
1474 /* This branch is predicted as not-taken.
1475 If this is a forward branch and it is near the end of a page,
1476 we've detected a problematic branch. */
1477 if (succeed && NIA > CIA) {
1478 if (PAGE_SIZE - (CIA & (PAGE_SIZE-1)) <= option_mpc860c0)
1479 program_interrupt(processor, cia, mpc860c0_instruction_program_interrupt);
1480 }
1481 }
1482 #endif // WITH_OPTION_MPC860C0
1483 if (CURRENT_MODEL_ISSUE > 0)
1484 model_branches(cpu_model(processor), succeed, BO);
1485 if (! BO{0}) {
1486 int reverse;
1487 if (BO{4}) { /* branch prediction bit set, reverse sense of test */
1488 reverse = EXTS(BD_0b00) < 0;
1489 } else { /* branch prediction bit not set */
1490 reverse = EXTS(BD_0b00) >= 0;
1491 }
1492 if (CURRENT_MODEL_ISSUE > 0)
1493 model_branch_predict(cpu_model(processor), reverse ? !succeed : succeed);
1494 }
1495
1496 0.19,6.BO,11.BI,16./,21.16,31.LK:XL:::Branch Conditional to Link Register
1497 *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1498 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1499 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1500 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1501 int M, ctr_ok, cond_ok, succeed;
1502 if (is_64bit_implementation && is_64bit_mode) M = 0;
1503 else M = 32;
1504 if (CURRENT_MODEL_ISSUE > 0 && ! BO{0})
1505 model_wait_for_cr(cpu_model(processor), BIT32_BI);
1506 if (!BO{2}) CTR = CTR - 1;
1507 ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != BO{3});
1508 cond_ok = BO{0} || (CR{BI} == BO{1});
1509 if (ctr_ok && cond_ok) {
1510 NIA = IEA(LR_0b00);
1511 succeed = 1;
1512 }
1513 else
1514 succeed = 0;
1515 if (LK) LR = (spreg)IEA(CIA + 4);
1516 #ifdef WITH_OPTION_MPC860C0
1517 if (option_mpc860c0 && (BO{0} && BO{2} || !BO{4})) {
1518 /* This branch is predicted as not-taken.
1519 If this is a forward branch and it is near the end of a page,
1520 we've detected a problematic branch. */
1521 if (succeed && NIA > CIA) {
1522 if (PAGE_SIZE - (CIA & (PAGE_SIZE-1)) <= option_mpc860c0)
1523 program_interrupt(processor, cia, mpc860c0_instruction_program_interrupt);
1524 }
1525 }
1526 #endif // WITH_OPTION_MPC860C0
1527 if (CURRENT_MODEL_ISSUE > 0) {
1528 model_branches(cpu_model(processor), succeed, BO);
1529 if (! BO{0})
1530 model_branch_predict(cpu_model(processor), BO{4} ? !succeed : succeed);
1531 }
1532
1533 0.19,6.BO,11.BI,16./,21.528,31.LK:XL:::Branch Conditional to Count Register
1534 *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1535 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1536 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1537 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1538 int cond_ok, succeed;
1539 if (CURRENT_MODEL_ISSUE > 0 && ! BO{0})
1540 model_wait_for_cr(cpu_model(processor), BIT32_BI);
1541 cond_ok = BO{0} || (CR{BI} == BO{1});
1542 if (cond_ok) {
1543 NIA = IEA(CTR_0b00);
1544 succeed = 1;
1545 }
1546 else
1547 succeed = 0;
1548 if (LK) LR = (spreg)IEA(CIA + 4);
1549 #ifdef WITH_OPTION_MPC860C0
1550 if (option_mpc860c0 && (BO{0} && BO{2} || !BO{4})) {
1551 /* This branch is predicted as not-taken.
1552 If this is a forward branch and it is near the end of a page,
1553 we've detected a problematic branch. */
1554 if (succeed && NIA > CIA) {
1555 if (PAGE_SIZE - (CIA & (PAGE_SIZE-1)) <= option_mpc860c0)
1556 program_interrupt(processor, cia, mpc860c0_instruction_program_interrupt);
1557 }
1558 }
1559 #endif // WITH_OPTION_MPC860C0
1560 if (CURRENT_MODEL_ISSUE > 0) {
1561 model_branches(cpu_model(processor), succeed, BO);
1562 if (! BO{0})
1563 model_branch_predict(cpu_model(processor), BO{4} ? !succeed : succeed);
1564 }
1565
1566 #
1567 # I.2.4.2 System Call Instruction
1568 #
1569 0.17,6./,11./,16./,30.1,31./:SC:::System Call
1570 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1571 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
1572 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
1573 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1574 if (CURRENT_MODEL_ISSUE > 0)
1575 model_serialize(MY_INDEX, cpu_model(processor));
1576 system_call_interrupt(processor, cia);
1577
1578 #
1579 # I.2.4.3 Condition Register Logical Instructions
1580 #
1581 0.19,6.BT,11.BA,16.BB,21.257,31./:XL::crand:Condition Register AND
1582 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1583 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1584 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1585 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1586 BLIT32(CR, BT, CR{BA} && CR{BB});
1587 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1588
1589 0.19,6.BT,11.BA,16.BB,21.449,31./:XL::cror:Condition Register OR
1590 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1591 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1592 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1593 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1594 BLIT32(CR, BT, CR{BA} || CR{BB});
1595 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1596
1597 0.19,6.BT,11.BA,16.BB,21.193,31./:XL::crxor:Condition Register XOR
1598 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1599 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1600 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1601 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1602 BLIT32(CR, BT, CR{BA} != CR{BB});
1603 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1604
1605 0.19,6.BT,11.BA,16.BB,21.225,31./:XL::crnand:Condition Register NAND
1606 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1607 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1608 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1609 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1610 BLIT32(CR, BT, !(CR{BA} && CR{BB}));
1611 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1612
1613 0.19,6.BT,11.BA,16.BB,21.33,31./:XL::crnor:Condition Register NOR
1614 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1615 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1616 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1617 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1618 BLIT32(CR, BT, !(CR{BA} || CR{BB}));
1619 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1620
1621 0.19,6.BT,11.BA,16.BB,21.289,31./:XL::creqv:Condition Register Equivalent
1622 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1623 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1624 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1625 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1626 BLIT32(CR, BT, CR{BA} == CR{BB});
1627 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1628
1629 0.19,6.BT,11.BA,16.BB,21.129,31./:XL::crandc:Condition Register AND with Complement
1630 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1631 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1632 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1633 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1634 BLIT32(CR, BT, CR{BA} && !CR{BB});
1635 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1636
1637 0.19,6.BT,11.BA,16.BB,21.417,31./:XL::crorc:Condition Register OR with Complement
1638 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1639 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1640 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1641 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1642 BLIT32(CR, BT, CR{BA} || !CR{BB});
1643 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1644
1645 #
1646 # I.2.4.4 Condition Register Field Instruction
1647 #
1648 0.19,6.BF,9./,11.BFA,14./,16./,21.0,31./:XL:::Move Condition Register Field
1649 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1650 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1651 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1652 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1653 MBLIT32(CR, 4*BF, 4*BF+3, EXTRACTED32(CR, 4*BFA, 4*BFA+3));
1654 PPC_INSN_CR(BF_BITMASK, 1 << BFA);
1655
1656
1657 #
1658 # I.3.3.2 Fixed-Point Load Instructions
1659 #
1660
1661 0.34,6.RT,11.RA,16.D:D:::Load Byte and Zero
1662 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1663 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1664 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1665 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1666 unsigned_word b;
1667 unsigned_word EA;
1668 if (RA_is_0) b = 0;
1669 else b = *rA;
1670 EA = b + EXTS(D);
1671 *rT = MEM(unsigned, EA, 1);
1672 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
1673
1674
1675 0.31,6.RT,11.RA,16.RB,21.87,31./:X:::Load Byte and Zero Indexed
1676 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1677 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1678 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1679 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1680 unsigned_word b;
1681 unsigned_word EA;
1682 if (RA_is_0) b = 0;
1683 else b = *rA;
1684 EA = b + *rB;
1685 *rT = MEM(unsigned, EA, 1);
1686 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
1687
1688 0.35,6.RT,11.RA,16.D:D:::Load Byte and Zero with Update
1689 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1690 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1691 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1692 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1693 unsigned_word EA;
1694 if (RA_is_0 || RA == RT)
1695 program_interrupt(processor, cia,
1696 illegal_instruction_program_interrupt);
1697 EA = *rA + EXTS(D);
1698 *rT = MEM(unsigned, EA, 1);
1699 *rA = EA;
1700 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK, 0);
1701
1702 0.31,6.RT,11.RA,16.RB,21.119,31./:X:::Load Byte and Zero with Update Indexed
1703 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1704 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1705 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1706 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1707 unsigned_word EA;
1708 if (RA_is_0 || RA == RT)
1709 program_interrupt(processor, cia,
1710 illegal_instruction_program_interrupt);
1711 EA = *rA + *rB;
1712 *rT = MEM(unsigned, EA, 1);
1713 *rA = EA;
1714 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK | RB_BITMASK, 0);
1715
1716 0.40,6.RT,11.RA,16.D:D:::Load Halfword and Zero
1717 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1718 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1719 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1720 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1721 unsigned_word b;
1722 unsigned_word EA;
1723 if (RA_is_0) b = 0;
1724 else b = *rA;
1725 EA = b + EXTS(D);
1726 *rT = MEM(unsigned, EA, 2);
1727 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
1728
1729 0.31,6.RT,11.RA,16.RB,21.279,31./:X:::Load Halfword and Zero Indexed
1730 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1731 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1732 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1733 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1734 unsigned_word b;
1735 unsigned_word EA;
1736 if (RA_is_0) b = 0;
1737 else b = *rA;
1738 EA = b + *rB;
1739 *rT = MEM(unsigned, EA, 2);
1740 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
1741
1742 0.41,6.RT,11.RA,16.D:D:::Load Halfword and Zero with Update
1743 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1744 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1745 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1746 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1747 unsigned_word EA;
1748 if (RA_is_0 || RA == RT)
1749 program_interrupt(processor, cia,
1750 illegal_instruction_program_interrupt);
1751 EA = *rA + EXTS(D);
1752 *rT = MEM(unsigned, EA, 2);
1753 *rA = EA;
1754 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK, 0);
1755
1756 0.31,6.RT,11.RA,16.RB,21.311,31./:X:::Load Halfword and Zero with Update Indexed
1757 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1758 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1759 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1760 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1761 unsigned_word EA;
1762 if (RA_is_0 || RA == RT)
1763 program_interrupt(processor, cia,
1764 illegal_instruction_program_interrupt);
1765 EA = *rA + *rB;
1766 *rT = MEM(unsigned, EA, 2);
1767 *rA = EA;
1768 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK | RB_BITMASK, 0);
1769
1770 0.42,6.RT,11.RA,16.D:D:::Load Halfword Algebraic
1771 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1772 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1773 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1774 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1775 unsigned_word b;
1776 unsigned_word EA;
1777 if (RA_is_0) b = 0;
1778 else b = *rA;
1779 EA = b + EXTS(D);
1780 *rT = MEM(signed, EA, 2);
1781 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
1782
1783 0.31,6.RT,11.RA,16.RB,21.343,31./:X:::Load Halfword Algebraic Indexed
1784 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1785 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1786 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1787 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1788 unsigned_word b;
1789 unsigned_word EA;
1790 if (RA_is_0) b = 0;
1791 else b = *rA;
1792 EA = b + *rB;
1793 *rT = MEM(signed, EA, 2);
1794 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
1795
1796 0.43,6.RT,11.RA,16.D:D:::Load Halfword Algebraic with Update
1797 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1798 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1799 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1800 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1801 unsigned_word EA;
1802 if (RA_is_0 || RA == RT)
1803 program_interrupt(processor, cia,
1804 illegal_instruction_program_interrupt);
1805 EA = *rA + EXTS(D);
1806 *rT = MEM(signed, EA, 2);
1807 *rA = EA;
1808 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK, 0);
1809
1810 0.31,6.RT,11.RA,16.RB,21.375,31./:X:::Load Halfword Algebraic with Update Indexed
1811 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1812 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1813 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1814 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1815 unsigned_word EA;
1816 if (RA_is_0 || RA == RT)
1817 program_interrupt(processor, cia,
1818 illegal_instruction_program_interrupt);
1819 EA = *rA + *rB;
1820 *rT = MEM(signed, EA, 2);
1821 *rA = EA;
1822 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK | RB_BITMASK, 0);
1823
1824 0.32,6.RT,11.RA,16.D:D:::Load Word and Zero
1825 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1826 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1827 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1828 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1829 unsigned_word b;
1830 unsigned_word EA;
1831 if (RA_is_0) b = 0;
1832 else b = *rA;
1833 EA = b + EXTS(D);
1834 *rT = MEM(unsigned, EA, 4);
1835 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
1836
1837 0.31,6.RT,11.RA,16.RB,21.23,31./:X:::Load Word and Zero Indexed
1838 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1839 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1840 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1841 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1842 unsigned_word b;
1843 unsigned_word EA;
1844 if (RA_is_0) b = 0;
1845 else b = *rA;
1846 EA = b + *rB;
1847 *rT = MEM(unsigned, EA, 4);
1848 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
1849
1850 0.33,6.RT,11.RA,16.D:D:::Load Word and Zero with Update
1851 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1852 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1853 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1854 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1855 unsigned_word EA;
1856 if (RA_is_0 || RA == RT)
1857 program_interrupt(processor, cia,
1858 illegal_instruction_program_interrupt);
1859 EA = *rA + EXTS(D);
1860 *rT = MEM(unsigned, EA, 4);
1861 *rA = EA;
1862 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK, 0);
1863
1864 0.31,6.RT,11.RA,16.RB,21.55,31./:X:::Load Word and Zero with Update Indexed
1865 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1866 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1867 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1868 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1869 unsigned_word EA;
1870 if (RA_is_0 || RA == RT)
1871 program_interrupt(processor, cia,
1872 illegal_instruction_program_interrupt);
1873 EA = *rA + *rB;
1874 *rT = MEM(unsigned, EA, 4);
1875 *rA = EA;
1876 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK | RB_BITMASK, 0);
1877
1878 0.58,6.RT,11.RA,16.DS,30.2:DS:64::Load Word Algebraic
1879 # unsigned_word b;
1880 # unsigned_word EA;
1881 # if (RA_is_0) b = 0;
1882 # else b = *rA;
1883 # EA = b + EXTS(DS_0b00);
1884 # *rT = MEM(signed, EA, 4);
1885
1886 0.31,6.RT,11.RA,16.RB,21.341,31./:X:64::Load Word Algebraic Indexed
1887 # unsigned_word b;
1888 # unsigned_word EA;
1889 # if (RA_is_0) b = 0;
1890 # else b = *rA;
1891 # EA = b + *rB;;
1892 # *rT = MEM(signed, EA, 4);
1893
1894 0.31,6.RT,11.RA,16.RB,21.373,31./:X:64::Load Word Algebraic with Update Indexed
1895 # unsigned_word EA;
1896 # if (RA_is_0 || RA == RT)
1897 # program_interrupt(processor, cia
1898 # illegal_instruction_program_interrupt);
1899 # EA = *rA + *rB;
1900 # *rT = MEM(signed, EA, 4);
1901 # *rA = EA;
1902
1903 0.58,6.RT,11.RA,16.DS,30.0:DS:64::Load Doubleword
1904 # unsigned_word b;
1905 # unsigned_word EA;
1906 # if (RA_is_0) b = 0;
1907 # else b = *rA;
1908 # EA = b + EXTS(DS_0b00);
1909 # *rT = MEM(unsigned, EA, 8);
1910
1911 0.31,6.RT,11.RA,16.RB,21.21,31./:X:64::Load Doubleword Indexed
1912 # unsigned_word b;
1913 # unsigned_word EA;
1914 # if (RA_is_0) b = 0;
1915 # else b = *rA;
1916 # EA = b + *rB;
1917 # *rT = MEM(unsigned, EA, 8);
1918
1919 0.58,6.RT,11.RA,16.DS,30.1:DS:64::Load Doubleword with Update
1920 # unsigned_word EA;
1921 # if (RA_is_0 || RA == RT)
1922 # program_interrupt(processor, cia
1923 # illegal_instruction_program_interrupt);
1924 # EA = *rA + EXTS(DS_0b00);
1925 # *rT = MEM(unsigned, EA, 8);
1926 # *rA = EA;
1927
1928 0.31,6.RT,11.RA,16.RB,21.53,31./:DS:64::Load Doubleword with Update Indexed
1929 # unsigned_word EA;
1930 # if (RA_is_0 || RA == RT)
1931 # program_interrupt(processor, cia
1932 # illegal_instruction_program_interrupt);
1933 # EA = *rA + *rB;
1934 # *rT = MEM(unsigned, EA, 8);
1935 # *rA = EA;
1936
1937
1938
1939 #
1940 # I.3.3.3 Fixed-Point Store Instructions
1941 #
1942
1943 0.38,6.RS,11.RA,16.D:D:::Store Byte
1944 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1945 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1946 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1947 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1948 unsigned_word b;
1949 unsigned_word EA;
1950 if (RA_is_0) b = 0;
1951 else b = *rA;
1952 EA = b + EXTS(D);
1953 STORE(EA, 1, *rS);
1954 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RS_BITMASK, 0);
1955
1956 0.31,6.RS,11.RA,16.RB,21.215,31./:X:::Store Byte Indexed
1957 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1958 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1959 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1960 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1961 unsigned_word b;
1962 unsigned_word EA;
1963 if (RA_is_0) b = 0;
1964 else b = *rA;
1965 EA = b + *rB;
1966 STORE(EA, 1, *rS);
1967 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
1968
1969 0.39,6.RS,11.RA,16.D:D:::Store Byte with Update
1970 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1971 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1972 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1973 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1974 unsigned_word EA;
1975 if (RA_is_0)
1976 program_interrupt(processor, cia,
1977 illegal_instruction_program_interrupt);
1978 EA = *rA + EXTS(D);
1979 STORE(EA, 1, *rS);
1980 *rA = EA;
1981 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RS_BITMASK, 0);
1982
1983 0.31,6.RS,11.RA,16.RB,21.247,31./:X:::Store Byte with Update Indexed
1984 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1985 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1986 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1987 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1988 unsigned_word EA;
1989 if (RA_is_0)
1990 program_interrupt(processor, cia,
1991 illegal_instruction_program_interrupt);
1992 EA = *rA + *rB;
1993 STORE(EA, 1, *rS);
1994 *rA = EA;
1995 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RB_BITMASK | RS_BITMASK, 0);
1996
1997 0.44,6.RS,11.RA,16.D:D:::Store Half Word
1998 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1999 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2000 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2001 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2002 unsigned_word b;
2003 unsigned_word EA;
2004 if (RA_is_0) b = 0;
2005 else b = *rA;
2006 EA = b + EXTS(D);
2007 STORE(EA, 2, *rS);
2008 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RS_BITMASK, 0);
2009
2010 0.31,6.RS,11.RA,16.RB,21.407,31./:X:::Store Half Word Indexed
2011 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2012 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2013 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2014 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2015 unsigned_word b;
2016 unsigned_word EA;
2017 if (RA_is_0) b = 0;
2018 else b = *rA;
2019 EA = b + *rB;
2020 STORE(EA, 2, *rS);
2021 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
2022
2023 0.45,6.RS,11.RA,16.D:D:::Store Half Word with Update
2024 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2025 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2026 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2027 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2028 unsigned_word EA;
2029 if (RA_is_0)
2030 program_interrupt(processor, cia,
2031 illegal_instruction_program_interrupt);
2032 EA = *rA + EXTS(D);
2033 STORE(EA, 2, *rS);
2034 *rA = EA;
2035 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RS_BITMASK, 0);
2036
2037 0.31,6.RS,11.RA,16.RB,21.439,31./:X:::Store Half Word with Update Indexed
2038 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2039 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2040 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2041 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2042 unsigned_word EA;
2043 if (RA_is_0)
2044 program_interrupt(processor, cia,
2045 illegal_instruction_program_interrupt);
2046 EA = *rA + *rB;
2047 STORE(EA, 2, *rS);
2048 *rA = EA;
2049 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RB_BITMASK | RS_BITMASK, 0);
2050
2051 0.36,6.RS,11.RA,16.D:D:::Store Word
2052 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2053 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2054 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2055 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2056 unsigned_word b;
2057 unsigned_word EA;
2058 if (RA_is_0) b = 0;
2059 else b = *rA;
2060 EA = b + EXTS(D);
2061 STORE(EA, 4, *rS);
2062 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RS_BITMASK, 0);
2063
2064 0.31,6.RS,11.RA,16.RB,21.151,31./:X:::Store Word Indexed
2065 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2066 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2067 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2068 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2069 unsigned_word b;
2070 unsigned_word EA;
2071 if (RA_is_0) b = 0;
2072 else b = *rA;
2073 EA = b + *rB;
2074 STORE(EA, 4, *rS);
2075 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
2076
2077 0.37,6.RS,11.RA,16.D:D:::Store Word with Update
2078 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2079 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2080 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2081 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2082 unsigned_word EA;
2083 if (RA_is_0)
2084 program_interrupt(processor, cia,
2085 illegal_instruction_program_interrupt);
2086 EA = *rA + EXTS(D);
2087 STORE(EA, 4, *rS);
2088 *rA = EA;
2089 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RS_BITMASK, 0);
2090
2091 0.31,6.RS,11.RA,16.RB,21.183,31./:X:::Store Word with Update 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
2096 unsigned_word EA;
2097 if (RA_is_0)
2098 program_interrupt(processor, cia,
2099 illegal_instruction_program_interrupt);
2100 EA = *rA + *rB;
2101 STORE(EA, 4, *rS);
2102 *rA = EA;
2103 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RB_BITMASK | RS_BITMASK, 0);
2104
2105 0.62,6.RS,11.RA,16.DS,30.0:DS:64::Store Doubleword
2106 # unsigned_word b;
2107 # unsigned_word EA;
2108 # if (RA_is_0) b = 0;
2109 # else b = *rA;
2110 # EA = b + EXTS(DS_0b00);
2111 # STORE(EA, 8, *rS);
2112 0.31,6.RS,11.RA,16.RB,21.149,31./:X:64::Store Doubleword Indexed
2113 # unsigned_word b;
2114 # unsigned_word EA;
2115 # if (RA_is_0) b = 0;
2116 # else b = *rA;
2117 # EA = b + *rB;
2118 # STORE(EA, 8, *rS);
2119 0.62,6.RS,11.RA,16.DS,30.1:DS:64::Store Doubleword with Update
2120 # unsigned_word EA;
2121 # if (RA_is_0)
2122 # program_interrupt(processor, cia
2123 # illegal_instruction_program_interrupt);
2124 # EA = *rA + EXTS(DS_0b00);
2125 # STORE(EA, 8, *rS);
2126 # *rA = EA;
2127 0.31,6.RS,11.RA,16.RB,21.181,31./:X:64::Store Doubleword with Update Indexed
2128 # unsigned_word EA;
2129 # if (RA_is_0)
2130 # program_interrupt(processor, cia
2131 # illegal_instruction_program_interrupt);
2132 # EA = *rA + *rB;
2133 # STORE(EA, 8, *rS);
2134 # *rA = EA;
2135
2136
2137 #
2138 # I.3.3.4 Fixed-Point Load and Store with Byte Reversal Instructions
2139 #
2140
2141 0.31,6.RT,11.RA,16.RB,21.790,31./:X:::Load Halfword Byte-Reverse Indexed
2142 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2143 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2144 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2145 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2146 unsigned_word b;
2147 unsigned_word EA;
2148 if (RA_is_0) b = 0;
2149 else b = *rA;
2150 EA = b + *rB;
2151 *rT = SWAP_2(MEM(unsigned, EA, 2));
2152 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
2153
2154 0.31,6.RT,11.RA,16.RB,21.534,31./:X:::Load Word Byte-Reverse Indexed
2155 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2156 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2157 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2158 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2159 unsigned_word b;
2160 unsigned_word EA;
2161 if (RA_is_0) b = 0;
2162 else b = *rA;
2163 EA = b + *rB;
2164 *rT = SWAP_4(MEM(unsigned, EA, 4));
2165 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
2166
2167 0.31,6.RS,11.RA,16.RB,21.918,31./:X:::Store Half Word Byte-Reversed Indexed
2168 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2169 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2170 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2171 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2172 unsigned_word b;
2173 unsigned_word EA;
2174 if (RA_is_0) b = 0;
2175 else b = *rA;
2176 EA = b + *rB;
2177 STORE(EA, 2, SWAP_2(*rS));
2178 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
2179
2180 0.31,6.RS,11.RA,16.RB,21.662,31./:X:::Store Word Byte-Reversed Indexed
2181 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2182 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2183 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2184 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2185 unsigned_word b;
2186 unsigned_word EA;
2187 if (RA_is_0) b = 0;
2188 else b = *rA;
2189 EA = b + *rB;
2190 STORE(EA, 4, SWAP_4(*rS));
2191 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
2192
2193
2194 #
2195 # I.3.3.5 Fixed-Point Load and Store Multiple Instrctions
2196 #
2197
2198 0.46,6.RT,11.RA,16.D:D:::Load Multiple Word
2199 unsigned_word EA;
2200 unsigned_word b;
2201 int r;
2202 if (RA_is_0) b = 0;
2203 else b = *rA;
2204 EA = b + EXTS(D);
2205 r = RT;
2206 if (RA >= r)
2207 program_interrupt(processor, cia,
2208 illegal_instruction_program_interrupt);
2209 if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT || (EA % 4 != 0))
2210 alignment_interrupt(processor, cia, EA);
2211 while (r <= 31) {
2212 GPR(r) = MEM(unsigned, EA, 4);
2213 r = r + 1;
2214 EA = EA + 4;
2215 }
2216
2217 0.47,6.RS,11.RA,16.D:D:::Store Multiple Word
2218 unsigned_word EA;
2219 unsigned_word b;
2220 int r;
2221 if (RA_is_0) b = 0;
2222 else b = *rA;
2223 EA = b + EXTS(D);
2224 if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT
2225 || (EA % 4 != 0))
2226 alignment_interrupt(processor, cia, EA);
2227 r = RS;
2228 while (r <= 31) {
2229 STORE(EA, 4, GPR(r));
2230 r = r + 1;
2231 EA = EA + 4;
2232 }
2233
2234
2235 #
2236 # I.3.3.6 Fixed-Point Move Assist Instructions
2237 #
2238
2239 0.31,6.RT,11.RA,16.NB,21.597,31./:X:::Load String Word Immediate
2240 unsigned_word EA;
2241 int n;
2242 int r;
2243 int i;
2244 int nr;
2245 if (RA_is_0) EA = 0;
2246 else EA = *rA;
2247 if (NB == 0) n = 32;
2248 else n = NB;
2249 r = RT - 1;
2250 i = 32;
2251 nr = (n + 3) / 4;
2252 if ((RT + nr >= 32)
2253 ? (RA >= RT || RA < (RT + nr) % 32)
2254 : (RA >= RT && RA < RT + nr))
2255 program_interrupt(processor, cia,
2256 illegal_instruction_program_interrupt);
2257 if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
2258 alignment_interrupt(processor, cia, EA);
2259 while (n > 0) {
2260 if (i == 32) {
2261 r = (r + 1) % 32;
2262 GPR(r) = 0;
2263 }
2264 GPR(r) |= INSERTED(MEM(unsigned, EA, 1), i, i+7);
2265 if (i == 64) i = 32;
2266 EA = EA + 1;
2267 n = n - 1;
2268 }
2269
2270 0.31,6.RT,11.RA,16.RB,21.533,31./:X:::Load String Word Indexed
2271 unsigned_word EA;
2272 unsigned_word b;
2273 int n;
2274 int r;
2275 int i;
2276 int nr;
2277 if (RA_is_0) b = 0;
2278 else b = *rA;
2279 EA = b + *rB;
2280 n = EXTRACTED32(XER, 25, 31);
2281 r = RT - 1;
2282 i = 32;
2283 nr = (n + 3) / 4;
2284 if (((RT + n >= 32)
2285 ? ((RA >= RT || RA < (RT + n) % 32)
2286 || (RB >= RT || RB < (RT + n) % 32))
2287 : ((RA >= RT && RA < RT + n)
2288 || (RB >= RT && RB < RT + n)))
2289 || (RT == RA || RT == RB))
2290 program_interrupt(processor, cia,
2291 illegal_instruction_program_interrupt);
2292 if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
2293 alignment_interrupt(processor, cia, EA);
2294 while (n > 0) {
2295 if (i == 32) {
2296 r = (r + 1) % 32;
2297 GPR(i) = 0;
2298 }
2299 GPR(r) |= INSERTED(MEM(unsigned, EA, 1), i, i+7);
2300 i = i + 8;
2301 if (i == 64) i = 32;
2302 EA = EA + 1;
2303 n = n - 1;
2304 }
2305
2306 0.31,6.RS,11.RA,16.NB,21.725,31./:X:::Store String Word Immedate
2307 unsigned_word EA;
2308 int n;
2309 int r;
2310 int i;
2311 if (RA_is_0) EA = 0;
2312 else EA = *rA;
2313 if (NB == 0) n = 32;
2314 else n = NB;
2315 r = RS - 1;
2316 i = 32;
2317 if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
2318 alignment_interrupt(processor, cia, EA);
2319 while (n > 0) {
2320 if (i == 32) r = (r + 1) % 32;
2321 STORE(EA, 1, EXTRACTED(GPR(r), i, i+7));
2322 i = i + 8;
2323 if (i == 64) i = 32;
2324 EA = EA + 1;
2325 n = n - 1;
2326 }
2327
2328 0.31,6.RS,11.RA,16.RB,21.661,31./:X:::Store String Word Indexed
2329 unsigned_word EA;
2330 unsigned_word b;
2331 int n;
2332 int r;
2333 int i;
2334 if (RA_is_0) b = 0;
2335 else b = *rA;
2336 EA = b + *rB;
2337 if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
2338 alignment_interrupt(processor, cia, EA);
2339 n = EXTRACTED32(XER, 25, 31);
2340 r = RS - 1;
2341 i = 32;
2342 while (n > 0) {
2343 if (i == 32) r = (r + 1) % 32;
2344 STORE(EA, 1, EXTRACTED(GPR(r), i, i+7));
2345 i = i + 8;
2346 if (i == 64) i = 32;
2347 EA = EA + 1;
2348 n = n - 1;
2349 }
2350
2351
2352 #
2353 # I.3.3.7 Storage Synchronization Instructions
2354 #
2355 # HACK: Rather than monitor addresses looking for a reason
2356 # to cancel a reservation. This code instead keeps
2357 # a copy of the data read from memory. Before performing
2358 # a store, the memory area is checked to see if it has
2359 # been changed.
2360 0.31,6.RT,11.RA,16.RB,21.20,31./:X:::Load Word And Reserve Indexed
2361 *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2362 *603: PPC_UNIT_LSU, PPC_UNIT_IU, 1, 2, 0
2363 *603e:PPC_UNIT_LSU, PPC_UNIT_IU, 1, 2, 0
2364 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2365 unsigned_word b;
2366 unsigned_word EA;
2367 if (RA_is_0) b = 0;
2368 else b = *rA;
2369 EA = b + *rB;
2370 RESERVE = 1;
2371 RESERVE_ADDR = real_addr(EA, 1/*is-read?*/);
2372 RESERVE_DATA = MEM(unsigned, EA, 4);
2373 *rT = RESERVE_DATA;
2374 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
2375
2376 0.31,6.RT,11.RA,16.RB,21.84,31./:X:64::Load Doubleword And Reserve Indexed
2377 unsigned_word b;
2378 unsigned_word EA;
2379 if (RA_is_0) b = 0;
2380 else b = *rA;
2381 EA = b + *rB;
2382 RESERVE = 1;
2383 RESERVE_ADDR = real_addr(EA, 1/*is-read?*/);
2384 RESERVE_DATA = MEM(unsigned, EA, 8);
2385 *rT = RESERVE_DATA;
2386 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
2387
2388 0.31,6.RS,11.RA,16.RB,21.150,31.1:X:::Store Word Conditional Indexed
2389 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2390 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 8, 8, 0
2391 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 8, 8, 0
2392 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 3, 0
2393 unsigned_word b;
2394 unsigned_word EA;
2395 if (RA_is_0) b = 0;
2396 else b = *rA;
2397 EA = b + *rB;
2398 if (RESERVE) {
2399 if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/)
2400 && /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 4)) {
2401 STORE(EA, 4, *rS);
2402 CR_SET_XER_SO(0, cr_i_zero);
2403 }
2404 else {
2405 /* ment to randomly to store, we never do! */
2406 CR_SET_XER_SO(0, 0);
2407 }
2408 RESERVE = 0;
2409 }
2410 else {
2411 CR_SET_XER_SO(0, 0);
2412 }
2413 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 1/*Rc*/);
2414
2415 0.31,6.RS,11.RA,16.RB,21.214,31.1:X:64::Store Doubleword Conditional Indexed
2416 unsigned_word b;
2417 unsigned_word EA;
2418 if (RA_is_0) b = 0;
2419 else b = *rA;
2420 EA = b + *rB;
2421 if (RESERVE) {
2422 if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/)
2423 && /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 8)) {
2424 STORE(EA, 8, *rS);
2425 CR_SET_XER_SO(0, cr_i_zero);
2426 }
2427 else {
2428 /* ment to randomly to store, we never do */
2429 CR_SET_XER_SO(0, 0);
2430 }
2431 RESERVE = 0;
2432 }
2433 else {
2434 CR_SET_XER_SO(0, 0);
2435 }
2436 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 1/*Rc*/);
2437
2438 0.31,6./,11./,16./,21.598,31./:X::sync:Synchronize
2439 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2440 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
2441 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
2442 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
2443 /* do nothing */
2444
2445
2446 #
2447 # I.3.3.9 Fixed-Point Arithmetic Instructions
2448 #
2449
2450 0.14,6.RT,11.RA,16.SI:D:::Add Immediate
2451 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2452 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2453 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2454 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2455 if (RA_is_0) *rT = EXTS(SI);
2456 else *rT = *rA + EXTS(SI);
2457 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rT, (long)*rT));
2458 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
2459
2460 0.15,6.RT,11.RA,16.SI:D:::Add Immediate Shifted
2461 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2462 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2463 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2464 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2465 if (RA_is_0) *rT = EXTS(SI) << 16;
2466 else *rT = *rA + (EXTS(SI) << 16);
2467 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rT, (long)*rT));
2468 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
2469
2470 0.31,6.RT,11.RA,16.RB,21.OE,22.266,31.Rc:XO:::Add
2471 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2472 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2473 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2474 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2475 ALU_BEGIN(*rA);
2476 ALU_ADD(*rB);
2477 ALU_END(*rT, 0/*CA*/, OE, Rc);
2478 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2479
2480 0.31,6.RT,11.RA,16.RB,21.OE,22.40,31.Rc:XO:::Subtract From
2481 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2482 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2483 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2484 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2485 ALU_BEGIN(*rA);
2486 ALU_NOT;
2487 ALU_ADD(*rB);
2488 ALU_ADD(1);
2489 ALU_END(*rT, 0/*CA*/, OE, Rc);
2490 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2491
2492 0.12,6.RT,11.RA,16.SI:D:::Add Immediate Carrying
2493 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2494 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2495 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2496 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2497 ALU_BEGIN(*rA);
2498 ALU_ADD(EXTS(SI));
2499 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
2500 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, 0/*Rc*/);
2501
2502 0.13,6.RT,11.RA,16.SI:D:::Add Immediate Carrying and Record
2503 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2504 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2505 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2506 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2507 ALU_BEGIN(*rA);
2508 ALU_ADD(EXTS(SI));
2509 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 1/*Rc*/);
2510 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, 1/*Rc*/);
2511
2512 0.8,6.RT,11.RA,16.SI:D:::Subtract From Immediate Carrying
2513 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2514 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2515 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2516 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2517 ALU_BEGIN(*rA);
2518 ALU_NOT;
2519 ALU_ADD(EXTS(SI));
2520 ALU_ADD(1);
2521 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
2522 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, 0/*Rc*/);
2523
2524 0.31,6.RT,11.RA,16.RB,21.OE,22.10,31.Rc:XO:::Add Carrying
2525 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2526 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2527 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2528 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2529 ALU_BEGIN(*rA);
2530 ALU_ADD(*rB);
2531 ALU_END(*rT, 1/*CA*/, OE, Rc);
2532 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2533
2534 0.31,6.RT,11.RA,16.RB,21.OE,22.8,31.Rc:XO:::Subtract From Carrying
2535 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2536 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2537 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2538 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2539 /* RT <- ~RA + RB + 1 === RT <- RB - RA */
2540 ALU_BEGIN(*rA);
2541 ALU_NOT;
2542 ALU_ADD(*rB);
2543 ALU_ADD(1);
2544 ALU_END(*rT, 1/*CA*/, OE, Rc);
2545 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2546
2547 0.31,6.RT,11.RA,16.RB,21.OE,22.138,31.Rc:XO:::Add Extended
2548 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2549 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2550 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2551 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2552 ALU_BEGIN(*rA);
2553 ALU_ADD(*rB);
2554 ALU_ADD_CA;
2555 ALU_END(*rT, 1/*CA*/, OE, Rc);
2556 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2557
2558 0.31,6.RT,11.RA,16.RB,21.OE,22.136,31.Rc:XO:::Subtract From Extended
2559 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2560 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2561 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2562 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2563 ALU_BEGIN(*rA);
2564 ALU_NOT;
2565 ALU_ADD(*rB);
2566 ALU_ADD_CA;
2567 ALU_END(*rT, 1/*CA*/, OE, Rc);
2568 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2569
2570 0.31,6.RT,11.RA,16./,21.OE,22.234,31.Rc:XO:::Add to Minus One Extended
2571 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2572 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2573 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2574 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2575 ALU_BEGIN(*rA);
2576 ALU_ADD_CA;
2577 ALU_ADD(-1);
2578 ALU_END(*rT, 1/*CA*/, OE, Rc);
2579 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2580
2581 0.31,6.RT,11.RA,16./,21.OE,22.232,31.Rc:XO:::Subtract From Minus One Extended
2582 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2583 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2584 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2585 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2586 ALU_BEGIN(*rA);
2587 ALU_NOT;
2588 ALU_ADD_CA;
2589 ALU_ADD(-1);
2590 ALU_END(*rT, 1/*CA*/, OE, Rc);
2591 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2592
2593 0.31,6.RT,11.RA,16./,21.OE,22.202,31.Rc:XO::addze:Add to Zero Extended
2594 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2595 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2596 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2597 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2598 ALU_BEGIN(*rA);
2599 ALU_ADD_CA;
2600 ALU_END(*rT, 1/*CA*/, OE, Rc);
2601 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2602
2603 0.31,6.RT,11.RA,16./,21.OE,22.200,31.Rc:XO:::Subtract from Zero Extended
2604 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2605 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2606 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2607 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2608 ALU_BEGIN(*rA);
2609 ALU_NOT;
2610 ALU_ADD_CA;
2611 ALU_END(*rT, 1/*CA*/, OE, Rc);
2612 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2613
2614 0.31,6.RT,11.RA,16./,21.OE,22.104,31.Rc:XO:::Negate
2615 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2616 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2617 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2618 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2619 ALU_BEGIN(*rA);
2620 ALU_NOT;
2621 ALU_ADD(1);
2622 ALU_END(*rT,0/*CA*/,OE,Rc);
2623 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2624
2625 0.7,6.RT,11.RA,16.SI:D::mulli:Multiply Low Immediate
2626 *601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2627 *603: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
2628 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
2629 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
2630 signed_word prod = *rA * EXTS(SI);
2631 *rT = prod;
2632 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, 0/*Rc*/);
2633
2634 0.31,6.RT,11.RA,16.RB,21.OE,22.233,31.Rc:D:64::Multiply Low Doubleword
2635
2636 0.31,6.RT,11.RA,16.RB,21.OE,22.235,31.Rc:XO::mullw:Multiply Low Word
2637 *601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2638 *603: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2639 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2640 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0
2641 signed64 a = (signed32)(*rA);
2642 signed64 b = (signed32)(*rB);
2643 signed64 prod = a * b;
2644 signed_word t = prod;
2645 *rT = *rA * *rB;
2646 if (t != prod && OE)
2647 XER |= (xer_overflow | xer_summary_overflow);
2648 CR0_COMPARE(t, 0, Rc);
2649 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2650
2651 0.31,6.RT,11.RA,16.RB,21./,22.73,31.Rc:XO:64::Multiply High Doubleword
2652
2653 0.31,6.RT,11.RA,16.RB,21./,22.75,31.Rc:XO::mulhw:Multiply High Word
2654 *601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2655 *603: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2656 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2657 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0
2658 signed64 a = (signed32)(*rA);
2659 signed64 b = (signed32)(*rB);
2660 signed64 prod = a * b;
2661 signed_word t = EXTRACTED64(prod, 0, 31);
2662 *rT = t;
2663 CR0_COMPARE(t, 0, Rc);
2664 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2665
2666 0.31,6.RT,11.RA,16.RB,21./,22.9,31.Rc:XO:64::Multiply High Doubleword Unsigned
2667
2668 0.31,6.RT,11.RA,16.RB,21./,22.11,31.Rc:XO::mulhwu:Multiply High Word Unsigned
2669 *601: PPC_UNIT_IU, PPC_UNIT_IU, 10, 10, 0
2670 *603: PPC_UNIT_IU, PPC_UNIT_IU, 6, 6, 0
2671 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 6, 6, 0
2672 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0
2673 unsigned64 a = (unsigned32)(*rA);
2674 unsigned64 b = (unsigned32)(*rB);
2675 unsigned64 prod = a * b;
2676 signed_word t = EXTRACTED64(prod, 0, 31);
2677 *rT = t;
2678 CR0_COMPARE(t, 0, Rc);
2679 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2680
2681 0.31,6.RT,11.RA,16.RB,21.OE,22.489,31.Rc:XO:64::Divide Doubleword
2682
2683 0.31,6.RT,11.RA,16.RB,21.OE,22.491,31.Rc:XO::divw:Divide Word
2684 *601: PPC_UNIT_IU, PPC_UNIT_IU, 36, 36, 0
2685 *603: PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2686 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2687 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 20, 20, 0
2688 signed64 dividend = (signed32)(*rA);
2689 signed64 divisor = (signed32)(*rB);
2690 if (divisor == 0 /* nb 0x8000..0 is sign extended */
2691 || (dividend == 0x80000000 && divisor == -1)) {
2692 if (OE)
2693 XER |= (xer_overflow | xer_summary_overflow);
2694 CR0_COMPARE(0, 0, Rc);
2695 }
2696 else {
2697 signed64 quotent = dividend / divisor;
2698 *rT = quotent;
2699 CR0_COMPARE((signed_word)quotent, 0, Rc);
2700 }
2701 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2702
2703 0.31,6.RT,11.RA,16.RB,21.OE,22.457,31.Rc:XO:64::Divide Doubleword Unsigned
2704
2705 0.31,6.RT,11.RA,16.RB,21.OE,22.459,31.Rc:XO::divwu:Divide Word Unsigned
2706 *601: PPC_UNIT_IU, PPC_UNIT_IU, 36, 36, 0
2707 *603: PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2708 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2709 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 20, 20, 0
2710 unsigned64 dividend = (unsigned32)(*rA);
2711 unsigned64 divisor = (unsigned32)(*rB);
2712 if (divisor == 0) {
2713 if (OE)
2714 XER |= (xer_overflow | xer_summary_overflow);
2715 CR0_COMPARE(0, 0, Rc);
2716 }
2717 else {
2718 unsigned64 quotent = dividend / divisor;
2719 *rT = quotent;
2720 CR0_COMPARE((signed_word)quotent, 0, Rc);
2721 }
2722 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2723
2724
2725 #
2726 # I.3.3.10 Fixed-Point Compare Instructions
2727 #
2728
2729 0.11,6.BF,9./,10.L,11.RA,16.SI:D:::Compare Immediate
2730 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2731 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2732 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2733 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2734 if (!is_64bit_mode && L)
2735 program_interrupt(processor, cia,
2736 illegal_instruction_program_interrupt);
2737 else {
2738 signed_word a;
2739 signed_word b = EXTS(SI);
2740 if (L == 0)
2741 a = EXTENDED(*rA);
2742 else
2743 a = *rA;
2744 CR_COMPARE(BF, a, b);
2745 }
2746 PPC_INSN_INT_CR(0, RA_BITMASK, BF_BITMASK);
2747
2748 0.31,6.BF,9./,10.L,11.RA,16.RB,21.0,31./:X:::Compare
2749 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2750 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2751 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2752 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2753 if (!is_64bit_mode && L)
2754 program_interrupt(processor, cia,
2755 illegal_instruction_program_interrupt);
2756 else {
2757 signed_word a;
2758 signed_word b;
2759 if (L == 0) {
2760 a = EXTENDED(*rA);
2761 b = EXTENDED(*rB);
2762 }
2763 else {
2764 a = *rA;
2765 b = *rB;
2766 }
2767 CR_COMPARE(BF, a, b);
2768 }
2769 PPC_INSN_INT_CR(0, RA_BITMASK | RB_BITMASK, BF_BITMASK);
2770
2771 0.10,6.BF,9./,10.L,11.RA,16.UI:D:::Compare Logical Immediate
2772 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2773 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2774 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2775 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2776 if (!is_64bit_mode && L)
2777 program_interrupt(processor, cia,
2778 illegal_instruction_program_interrupt);
2779 else {
2780 unsigned_word a;
2781 unsigned_word b = UI;
2782 if (L == 0)
2783 a = MASKED(*rA, 32, 63);
2784 else
2785 a = *rA;
2786 CR_COMPARE(BF, a, b);
2787 }
2788 PPC_INSN_INT_CR(0, RA_BITMASK, BF_BITMASK);
2789
2790 0.31,6.BF,9./,10.L,11.RA,16.RB,21.32,31./:X:::Compare Logical
2791 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2792 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2793 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2794 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2795 if (!is_64bit_mode && L)
2796 program_interrupt(processor, cia,
2797 illegal_instruction_program_interrupt);
2798 else {
2799 unsigned_word a;
2800 unsigned_word b;
2801 if (L == 0) {
2802 a = MASKED(*rA, 32, 63);
2803 b = MASKED(*rB, 32, 63);
2804 }
2805 else {
2806 a = *rA;
2807 b = *rB;
2808 }
2809 CR_COMPARE(BF, a, b);
2810 }
2811 PPC_INSN_INT_CR(0, RA_BITMASK | RB_BITMASK, BF_BITMASK);
2812
2813
2814 #
2815 # I.3.3.11 Fixed-Point Trap Instructions
2816 #
2817
2818 0.2,6.TO,11.RA,16.SI:D:64::Trap Doubleword Immediate
2819 if (!is_64bit_mode)
2820 program_interrupt(processor, cia,
2821 illegal_instruction_program_interrupt);
2822 else {
2823 signed_word a = *rA;
2824 signed_word b = EXTS(SI);
2825 if ((a < b && TO{0})
2826 || (a > b && TO{1})
2827 || (a == b && TO{2})
2828 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2829 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2830 )
2831 program_interrupt(processor, cia,
2832 trap_program_interrupt);
2833 }
2834
2835 0.3,6.TO,11.RA,16.SI:D:::Trap Word Immediate
2836 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2837 *603: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2838 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2839 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2840 signed_word a = EXTENDED(*rA);
2841 signed_word b = EXTS(SI);
2842 if ((a < b && TO{0})
2843 || (a > b && TO{1})
2844 || (a == b && TO{2})
2845 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2846 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2847 )
2848 program_interrupt(processor, cia,
2849 trap_program_interrupt);
2850
2851 0.31,6.TO,11.RA,16.RB,21.68,31./:X:64::Trap Doubleword
2852 if (!is_64bit_mode)
2853 program_interrupt(processor, cia,
2854 illegal_instruction_program_interrupt);
2855 else {
2856 signed_word a = *rA;
2857 signed_word b = *rB;
2858 if ((a < b && TO{0})
2859 || (a > b && TO{1})
2860 || (a == b && TO{2})
2861 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2862 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2863 )
2864 program_interrupt(processor, cia,
2865 trap_program_interrupt);
2866 }
2867
2868 0.31,6.TO,11.RA,16.RB,21.4,31./:X:::Trap Word
2869 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2870 *603: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2871 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2872 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2873 signed_word a = EXTENDED(*rA);
2874 signed_word b = EXTENDED(*rB);
2875 if (TO == 12 && rA == rB) {
2876 ITRACE(trace_breakpoint, ("breakpoint\n"));
2877 cpu_halt(processor, cia, was_trap, 0);
2878 }
2879 else if ((a < b && TO{0})
2880 || (a > b && TO{1})
2881 || (a == b && TO{2})
2882 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2883 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2884 )
2885 program_interrupt(processor, cia,
2886 trap_program_interrupt);
2887
2888 #
2889 # I.3.3.12 Fixed-Point Logical Instructions
2890 #
2891
2892 0.28,6.RS,11.RA,16.UI:D:::AND Immediate
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
2897 *rA = *rS & UI;
2898 CR0_COMPARE(*rA, 0, 1/*Rc*/);
2899 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2900 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 1/*Rc*/);
2901
2902 0.29,6.RS,11.RA,16.UI:D:::AND Immediate Shifted
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
2907 *rA = *rS & (UI << 16);
2908 CR0_COMPARE(*rA, 0, 1/*Rc*/);
2909 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2910 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 1/*Rc*/);
2911
2912 0.24,6.RS,11.RA,16.UI:D:::OR Immediate
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
2917 *rA = *rS | UI;
2918 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2919 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 0/*Rc*/);
2920
2921 0.25,6.RS,11.RA,16.UI:D:::OR Immediate Shifted
2922 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2923 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2924 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2925 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2926 *rA = *rS | (UI << 16);
2927 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2928 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 0/*Rc*/);
2929
2930 0.26,6.RS,11.RA,16.UI:D:::XOR Immediate
2931 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2932 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2933 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2934 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2935 *rA = *rS ^ UI;
2936 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2937 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 0/*Rc*/);
2938
2939 0.27,6.RS,11.RA,16.UI:D:::XOR Immediate Shifted
2940 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2941 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2942 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2943 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2944 *rA = *rS ^ (UI << 16);
2945 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2946 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 0/*Rc*/);
2947
2948 0.31,6.RS,11.RA,16.RB,21.28,31.Rc:X:::AND
2949 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2950 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2951 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2952 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2953 *rA = *rS & *rB;
2954 CR0_COMPARE(*rA, 0, Rc);
2955 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2956 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2957
2958 0.31,6.RS,11.RA,16.RB,21.444,31.Rc:X:::OR
2959 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2960 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2961 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2962 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2963 *rA = *rS | *rB;
2964 CR0_COMPARE(*rA, 0, Rc);
2965 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2966 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2967
2968 0.31,6.RS,11.RA,16.RB,21.316,31.Rc:X:::XOR
2969 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2970 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2971 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2972 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2973 *rA = *rS ^ *rB;
2974 CR0_COMPARE(*rA, 0, Rc);
2975 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2976 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2977
2978 0.31,6.RS,11.RA,16.RB,21.476,31.Rc:X:::NAND
2979 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2980 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2981 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2982 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2983 *rA = ~(*rS & *rB);
2984 CR0_COMPARE(*rA, 0, Rc);
2985 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2986 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2987
2988 0.31,6.RS,11.RA,16.RB,21.124,31.Rc:X:::NOR
2989 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2990 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2991 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2992 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2993 *rA = ~(*rS | *rB);
2994 CR0_COMPARE(*rA, 0, Rc);
2995 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2996 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2997
2998 0.31,6.RS,11.RA,16.RB,21.284,31.Rc:X:::Equivalent
2999 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3000 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3001 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3002 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3003 *rA = ~(*rS ^ *rB); /* A === B */
3004 CR0_COMPARE(*rA, 0, Rc);
3005 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3006 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
3007
3008 0.31,6.RS,11.RA,16.RB,21.60,31.Rc:X:::AND with Complement
3009 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3010 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3011 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3012 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3013 *rA = *rS & ~*rB;
3014 CR0_COMPARE(*rA, 0, Rc);
3015 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3016 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
3017
3018 0.31,6.RS,11.RA,16.RB,21.412,31.Rc:X:::OR with Complement
3019 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3020 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3021 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3022 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3023 *rA = *rS | ~*rB;
3024 CR0_COMPARE(*rA, 0, Rc);
3025 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3026 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
3027
3028 0.31,6.RS,11.RA,16./,21.954,31.Rc:X::extsb:Extend Sign Byte
3029 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3030 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3031 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3032 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3033 *rA = (signed_word)(signed8)*rS;
3034 CR0_COMPARE(*rA, 0, Rc);
3035 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3036 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3037
3038 0.31,6.RS,11.RA,16./,21.922,31.Rc:X::extsh:Extend Sign Half Word
3039 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3040 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3041 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3042 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3043 *rA = (signed_word)(signed16)*rS;
3044 CR0_COMPARE(*rA, 0, Rc);
3045 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3046 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3047
3048 0.31,6.RS,11.RA,16./,21.986,31.Rc:X:64::Extend Sign Word
3049 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3050 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3051 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3052 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3053 # *rA = (signed_word)(signed32)*rS;
3054 # CR0_COMPARE(*rA, 0, Rc);
3055
3056 0.31,6.RS,11.RA,16./,21.58,31.Rc:X:64::Count Leading Zeros Doubleword
3057 # int count = 0;
3058 # unsigned64 mask = BIT64(0);
3059 # unsigned64 source = *rS;
3060 # while (!(source & mask) && mask != 0) {
3061 # mask >>= 1;
3062 # count++;
3063 # }
3064 # *rA = count;
3065 # CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */
3066
3067 0.31,6.RS,11.RA,16./,21.26,31.Rc:X:::Count Leading Zeros Word
3068 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3069 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3070 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3071 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3072 int count = 0;
3073 unsigned32 mask = BIT32(0);
3074 unsigned32 source = *rS;
3075 while (!(source & mask) && mask != 0) {
3076 mask >>= 1;
3077 count++;
3078 }
3079 *rA = count;
3080 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3081 CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */
3082
3083
3084 #
3085 # I.3.3.13 Fixed-Point Rotate and Shift Instructions
3086 #
3087
3088 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
3089 # long n = (sh_5 << 4) | sh_0_4;
3090 # unsigned_word r = ROTL64(*rS, n);
3091 # long b = (mb_5 << 4) | mb_0_4;
3092 # unsigned_word m = MASK(b, 63);
3093 # signed_word result = r & m;
3094 # *rA = result;
3095 # ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3096 # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
3097
3098 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
3099 # long n = (sh_5 << 4) | sh_0_4;
3100 # unsigned_word r = ROTL64(*rS, n);
3101 # long e = (me_5 << 4) | me_0_4;
3102 # unsigned_word m = MASK(0, e);
3103 # signed_word result = r & m;
3104 # *rA = result;
3105 # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
3106
3107 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
3108 # long n = (sh_5 << 4) | sh_0_4;
3109 # unsigned_word r = ROTL64(*rS, n);
3110 # long b = (mb_5 << 4) | mb_0_4;
3111 # unsigned_word m = MASK(0, (64-n));
3112 # signed_word result = r & m;
3113 # *rA = result;
3114 # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
3115
3116 0.21,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M:::Rotate Left Word Immediate then AND with Mask
3117 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3118 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3119 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3120 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3121 long n = SH;
3122 unsigned32 s = *rS;
3123 unsigned32 r = ROTL32(s, n);
3124 unsigned32 m = MASK(MB+32, ME+32);
3125 signed_word result = r & m;
3126 *rA = result;
3127 CR0_COMPARE(result, 0, Rc);
3128 ITRACE(trace_alu,
3129 ("n=%ld, s=0x%lx, r=0x%lx, m=0x%lx, result=0x%lx, cr=0x%lx\n",
3130 n, (unsigned long)s, (unsigned long)r, (unsigned long)m,
3131 (unsigned long)result, (unsigned long)CR));
3132 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3133
3134 0.30,6.RS,11.RA,16.RB,21.mb,27.8,31.Rc:MDS:64::Rotate Left Doubleword then Clear Left
3135 # long n = MASKED(*rB, 58, 63);
3136 # unsigned_word r = ROTL64(*rS, n);
3137 # long b = (mb_5 << 4) | mb_0_4;
3138 # unsigned_word m = MASK(b, 63);
3139 # signed_word result = r & m;
3140 # *rA = result;
3141 # CR0_COMPARE(result, 0, Rc);
3142
3143 0.30,6.RS,11.RA,16.RB,21.me,27.9,31.Rc:MDS:64::Rotate Left Doubleword then Clear Right
3144 # long n = MASKED(*rB, 58, 63);
3145 # unsigned_word r = ROTL64(*rS, n);
3146 # long e = (me_5 << 4) | me_0_4;
3147 # unsigned_word m = MASK(0, e);
3148 # signed_word result = r & m;
3149 # *rA = result;
3150 # CR0_COMPARE(result, 0, Rc);
3151
3152 0.23,6.RS,11.RA,16.RB,21.MB,26.ME,31.Rc:M:::Rotate Left Word then AND with Mask
3153 long n = MASKED(*rB, 59, 63);
3154 unsigned32 r = ROTL32(*rS, n);
3155 unsigned32 m = MASK(MB+32, ME+32);
3156 signed_word result = r & m;
3157 *rA = result;
3158 CR0_COMPARE(result, 0, Rc);
3159
3160 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
3161 # long n = (sh_5 << 4) | sh_0_4;
3162 # unsigned_word r = ROTL64(*rS, n);
3163 # long b = (mb_5 << 4) | mb_0_4;
3164 # unsigned_word m = MASK(b, (64-n));
3165 # signed_word result = (r & m) | (*rA & ~m)
3166 # *rA = result;
3167 # CR0_COMPARE(result, 0, Rc);
3168
3169 0.20,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M::rlwimi:Rotate Left Word Immediate then Mask Insert
3170 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3171 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3172 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3173 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3174 long n = SH;
3175 unsigned32 r = ROTL32(*rS, n);
3176 unsigned32 m = MASK(MB+32, ME+32);
3177 signed_word result = (r & m) | (*rA & ~m);
3178 *rA = result;
3179 ITRACE(trace_alu, (": n=%ld *rS=0x%lx r=0x%lx m=0x%lx result=0x%lx\n",
3180 n, (unsigned long)*rS, (unsigned long)r, (unsigned long)m,
3181 (unsigned long)result));
3182 CR0_COMPARE(result, 0, Rc);
3183 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3184
3185
3186 0.31,6.RS,11.RA,16.RB,21.27,31.Rc:X:64::Shift Left Doubleword
3187
3188 0.31,6.RS,11.RA,16.RB,21.24,31.Rc:X:::Shift Left Word
3189 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3190 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3191 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3192 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3193 int n = MASKED(*rB, 58, 63);
3194 unsigned32 source = *rS;
3195 signed_word shifted;
3196 if (n < 32)
3197 shifted = (source << n);
3198 else
3199 shifted = 0;
3200 *rA = shifted;
3201 CR0_COMPARE(shifted, 0, Rc);
3202 ITRACE(trace_alu,
3203 ("n=%d, source=0x%lx, shifted=0x%lx\n",
3204 n, (unsigned long)source, (unsigned long)shifted));
3205 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3206
3207 0.31,6.RS,11.RA,16.RB,21.539,31.Rc:X:64::Shift Right Doubleword
3208
3209 0.31,6.RS,11.RA,16.RB,21.536,31.Rc:X:::Shift Right Word
3210 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3211 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3212 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3213 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3214 int n = MASKED(*rB, 58, 63);
3215 unsigned32 source = *rS;
3216 signed_word shifted;
3217 if (n < 32)
3218 shifted = (source >> n);
3219 else
3220 shifted = 0;
3221 *rA = shifted;
3222 CR0_COMPARE(shifted, 0, Rc);
3223 ITRACE(trace_alu, \
3224 ("n=%d, source=0x%lx, shifted=0x%lx\n",
3225 n, (unsigned long)source, (unsigned long)shifted));
3226 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3227
3228 0.31,6.RS,11.RA,16.sh_0_4,21.413,30.sh_5,31.Rc:XS:64::Shift Right Algebraic Doubleword Immediate
3229
3230 0.31,6.RS,11.RA,16.SH,21.824,31.Rc:X:::Shift Right Algebraic Word Immediate
3231 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3232 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3233 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3234 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3235 int n = SH;
3236 signed_word r = ROTL32(*rS, /*64*/32-n);
3237 signed_word m = MASK(n+32, 63);
3238 int S = MASKED(*rS, 32, 32);
3239 signed_word shifted = (r & m) | (S ? ~m : 0);
3240 *rA = shifted;
3241 if (S && ((r & ~m) & MASK(32, 63)) != 0)
3242 XER |= xer_carry;
3243 else
3244 XER &= ~xer_carry;
3245 CR0_COMPARE(shifted, 0, Rc);
3246 ITRACE(trace_alu, (" Result = %ld (0x%lx), XER = %ld\n",
3247 (long)*rA, (long)*rA, (long)XER));
3248 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3249
3250 0.31,6.RS,11.RA,16.RB,21.794,31.Rc:X:64::Shift Right Algebraic Doubleword
3251
3252 0.31,6.RS,11.RA,16.RB,21.792,31.Rc:X:::Shift Right Algebraic Word
3253 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3254 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3255 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3256 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3257 unsigned64 mask;
3258 int n = MASKED(*rB, 59, 63);
3259 signed32 source = (signed32)*rS; /* signed to keep sign bit */
3260 signed32 shifted = source >> n;
3261 int S = (MASKED(*rS,32,32) != 0);
3262 signed64 r = ((unsigned64) source);
3263 r = ((unsigned64) source) << 32 | (unsigned32) source;
3264 r = ROTL64(r,64-n);
3265 if (MASKED(*rB,58,58) == 0)
3266 mask = (unsigned64) MASK64(n+32,63);
3267 else
3268 mask = (unsigned64) 0;
3269 *rA = (signed_word) (r & mask | ((signed64) -1*S) & ~mask); /* if 64bit will sign extend */
3270 if (S && (MASKED(r & ~mask,32,63)!=0))
3271 XER |= xer_carry;
3272 else
3273 XER &= ~xer_carry;
3274 CR0_COMPARE(*rA, 0, Rc);
3275 ITRACE(trace_alu, (" Result = %ld (0x%lx), XER = %ld\n",
3276 (long)*rA, (long)*rA, (long)XER));
3277 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3278
3279 #
3280 # I.3.3.14 Move to/from System Register Instructions
3281 #
3282
3283 0.31,6.RS,11.SPR,21.467,31./:XFX::mtspr %SPR, %RS:Move to Special Purpose Register
3284 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3285 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
3286 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
3287 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
3288 int n = (SPR{5:9} << 5) | SPR{0:4};
3289 if (SPR{0} && IS_PROBLEM_STATE(processor))
3290 program_interrupt(processor, cia,
3291 privileged_instruction_program_interrupt);
3292 else if (!spr_is_valid(n)
3293 || spr_is_readonly(n))
3294 program_interrupt(processor, cia,
3295 illegal_instruction_program_interrupt);
3296 else {
3297 spreg new_val = (spr_length(n) == 64
3298 ? *rS
3299 : MASKED(*rS, 32, 63));
3300 /* HACK - time base registers need to be updated immediatly */
3301 if (WITH_TIME_BASE) {
3302 switch (n) {
3303 case spr_tbu:
3304 cpu_set_time_base(processor,
3305 (MASKED64(cpu_get_time_base(processor), 32, 63)
3306 | INSERTED64(new_val, 0, 31)));
3307 break;
3308 case spr_tbl:
3309 cpu_set_time_base(processor,
3310 (MASKED64(cpu_get_time_base(processor), 0, 31)
3311 | INSERTED64(new_val, 32, 63)));
3312 break;
3313 case spr_dec:
3314 cpu_set_decrementer(processor, new_val);
3315 break;
3316 default:
3317 SPREG(n) = new_val;
3318 break;
3319 }
3320 }
3321 else {
3322 SPREG(n) = new_val;
3323 }
3324 }
3325 PPC_INSN_TO_SPR(RS_BITMASK, n);
3326
3327 0.31,6.RT,11.SPR,21.339,31./:XFX::mfspr %RT, %SPR:Move from Special Purpose Register
3328 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3329 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3330 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3331 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
3332 int n = (SPR{5:9} << 5) | SPR{0:4};
3333 if (SPR{0} && IS_PROBLEM_STATE(processor))
3334 program_interrupt(processor, cia,
3335 privileged_instruction_program_interrupt);
3336 else if (!spr_is_valid(n))
3337 program_interrupt(processor, cia,
3338 illegal_instruction_program_interrupt);
3339 else {
3340 /* HACK - time base registers need to be calculated */
3341 if (WITH_TIME_BASE) {
3342 switch (n) {
3343 case spr_dec:
3344 *rT = cpu_get_decrementer(processor);
3345 break;
3346 case spr_tbu:
3347 case spr_tbl:
3348 /* NOTE - these SPR's are not readable. Use mftb[ul] */
3349 default:
3350 *rT = SPREG(n);
3351 break;
3352 }
3353 }
3354 else {
3355 *rT = SPREG(n);
3356 }
3357 }
3358 PPC_INSN_FROM_SPR(RT_BITMASK, n);
3359
3360 0.31,6.RS,11./,12.FXM,20./,21.144,31./:XFX::mtfcr:Move to Condition Register Fields
3361 *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
3362 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3363 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3364 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
3365 if (FXM == 0xff) {
3366 CR = *rS;
3367 }
3368 else {
3369 unsigned_word mask = 0;
3370 unsigned_word f;
3371 for (f = 0; f < 8; f++) {
3372 if (FXM & (0x80 >> f))
3373 mask |= (0xf << 4*(7-f));
3374 }
3375 CR = (MASKED(*rS, 32, 63) & mask) | (CR & ~mask);
3376 }
3377 PPC_INSN_MTCR(RS_BITMASK, FXM);
3378
3379 0.31,6.BF,9./,11./,16./,21.512,31./:X:::Move to Condition Register from XER
3380 # CR_SET(BF, EXTRACTED32(XER, 0, 3));
3381 # MBLIT32(XER, 0, 3, 0);
3382
3383 0.31,6.RT,11./,16./,21.19,31./:X:::Move From Condition Register
3384 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3385 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3386 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3387 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
3388 *rT = (unsigned32)CR;
3389 PPC_INSN_MFCR(RT_BITMASK);
3390
3391 #
3392 # I.4.6.2 Floating-Point Load Instructions
3393 #
3394
3395 0.48,6.FRT,11.RA,16.D:D:f:lfs:Load Floating-Point Single
3396 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3397 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3398 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3399 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3400 unsigned_word b;
3401 unsigned_word EA;
3402 if (RA_is_0) b = 0;
3403 else b = *rA;
3404 EA = b + EXTS(D);
3405 *frT = DOUBLE(MEM(unsigned, EA, 4));
3406 PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3407
3408 0.31,6.FRT,11.RA,16.RB,21.535,31./:X:f::Load Floating-Point Single Indexed
3409 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3410 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3411 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3412 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3413 unsigned_word b;
3414 unsigned_word EA;
3415 if (RA_is_0) b = 0;
3416 else b = *rA;
3417 EA = b + *rB;
3418 *frT = DOUBLE(MEM(unsigned, EA, 4));
3419 PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3420
3421 0.49,6.FRT,11.RA,16.D:D:f::Load Floating-Point Single with Update
3422 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3423 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3424 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3425 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3426 unsigned_word EA;
3427 if (RA_is_0)
3428 program_interrupt(processor, cia,
3429 illegal_instruction_program_interrupt);
3430 EA = *rA + EXTS(D);
3431 *frT = DOUBLE(MEM(unsigned, EA, 4));
3432 *rA = EA;
3433 PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3434
3435 0.31,6.FRT,11.RA,16.RB,21.576,31./:X:f::Load Floating-Point Single with Update Indexed
3436 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3437 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3438 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3439 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3440 unsigned_word EA;
3441 if (RA_is_0)
3442 program_interrupt(processor, cia,
3443 illegal_instruction_program_interrupt);
3444 EA = *rA + *rB;
3445 *frT = DOUBLE(MEM(unsigned, EA, 4));
3446 *rA = EA;
3447 PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3448
3449 0.50,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double
3450 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3451 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3452 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3453 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3454 unsigned_word b;
3455 unsigned_word EA;
3456 if (RA_is_0) b = 0;
3457 else b = *rA;
3458 EA = b + EXTS(D);
3459 *frT = MEM(unsigned, EA, 8);
3460 PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3461
3462 0.31,6.FRT,11.RA,16.RB,21.599,31./:X:f::Load Floating-Point Double Indexed
3463 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3464 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3465 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3466 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3467 unsigned_word b;
3468 unsigned_word EA;
3469 if (RA_is_0) b = 0;
3470 else b = *rA;
3471 EA = b + *rB;
3472 *frT = MEM(unsigned, EA, 8);
3473 PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3474
3475 0.51,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double with Update
3476 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3477 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3478 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3479 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3480 unsigned_word EA;
3481 if (RA_is_0)
3482 program_interrupt(processor, cia,
3483 illegal_instruction_program_interrupt);
3484 EA = *rA + EXTS(D);
3485 *frT = MEM(unsigned, EA, 8);
3486 *rA = EA;
3487 PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3488
3489 0.31,6.FRT,11.RA,16.RB,21.631,31./:X:f::Load Floating-Point Double with Update Indexed
3490 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3491 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3492 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3493 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3494 unsigned_word EA;
3495 if (RA_is_0)
3496 program_interrupt(processor, cia,
3497 illegal_instruction_program_interrupt);
3498 EA = *rA + *rB;
3499 *frT = MEM(unsigned, EA, 8);
3500 *rA = EA;
3501 PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3502
3503
3504 #
3505 # I.4.6.3 Floating-Point Store Instructions
3506 #
3507
3508 0.52,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single
3509 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3510 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3511 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3512 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3513 unsigned_word b;
3514 unsigned_word EA;
3515 if (RA_is_0) b = 0;
3516 else b = *rA;
3517 EA = b + EXTS(D);
3518 STORE(EA, 4, SINGLE(*frS));
3519 PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3520
3521 0.31,6.FRS,11.RA,16.RB,21.663,31./:X:f::Store Floating-Point Single Indexed
3522 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3523 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3524 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3525 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3526 unsigned_word b;
3527 unsigned_word EA;
3528 if (RA_is_0) b = 0;
3529 else b = *rA;
3530 EA = b + *rB;
3531 STORE(EA, 4, SINGLE(*frS));
3532 PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3533
3534 0.53,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single with Update
3535 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3536 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3537 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3538 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3539 unsigned_word EA;
3540 if (RA_is_0)
3541 program_interrupt(processor, cia,
3542 illegal_instruction_program_interrupt);
3543 EA = *rA + EXTS(D);
3544 STORE(EA, 4, SINGLE(*frS));
3545 *rA = EA;
3546 PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3547
3548 0.31,6.FRS,11.RA,16.RB,21.695,31./:X:f::Store Floating-Point Single with Update Indexed
3549 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3550 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3551 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3552 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3553 unsigned_word EA;
3554 if (RA_is_0)
3555 program_interrupt(processor, cia,
3556 illegal_instruction_program_interrupt);
3557 EA = *rA + *rB;
3558 STORE(EA, 4, SINGLE(*frS));
3559 *rA = EA;
3560 PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3561
3562 0.54,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double
3563 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3564 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3565 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3566 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3567 unsigned_word b;
3568 unsigned_word EA;
3569 if (RA_is_0) b = 0;
3570 else b = *rA;
3571 EA = b + EXTS(D);
3572 STORE(EA, 8, *frS);
3573 PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3574
3575 0.31,6.FRS,11.RA,16.RB,21.727,31./:X:f::Store Floating-Point Double Indexed
3576 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3577 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3578 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3579 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3580 unsigned_word b;
3581 unsigned_word EA;
3582 if (RA_is_0) b = 0;
3583 else b = *rA;
3584 EA = b + *rB;
3585 STORE(EA, 8, *frS);
3586 PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3587
3588 0.55,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double with Update
3589 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3590 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3591 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3592 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3593 unsigned_word EA;
3594 if (RA_is_0)
3595 program_interrupt(processor, cia,
3596 illegal_instruction_program_interrupt);
3597 EA = *rA + EXTS(D);
3598 STORE(EA, 8, *frS);
3599 *rA = EA;
3600 PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3601
3602 0.31,6.FRS,11.RA,16.RB,21.759,31./:X:f::Store Floating-Point Double with Update Indexed
3603 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3604 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3605 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3606 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3607 unsigned_word EA;
3608 if (RA_is_0)
3609 program_interrupt(processor, cia,
3610 illegal_instruction_program_interrupt);
3611 EA = *rA + *rB;
3612 STORE(EA, 8, *frS);
3613 *rA = EA;
3614 PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3615
3616
3617 #
3618 # I.4.6.4 Floating-Point Move Instructions
3619 #
3620
3621 0.63,6.FRT,11./,16.FRB,21.72,31.Rc:X:f::Floating Move Register
3622 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3623 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3624 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3625 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3626 *frT = *frB;
3627 CR1_UPDATE(Rc);
3628 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3629
3630 0.63,6.FRT,11./,16.FRB,21.40,31.Rc:X:f::Floating Negate
3631 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3632 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3633 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3634 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3635 *frT = *frB ^ BIT64(0);
3636 CR1_UPDATE(Rc);
3637 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3638
3639 0.63,6.FRT,11./,16.FRB,21.264,31.Rc:X:f::Floating Absolute Value
3640 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3641 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3642 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3643 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3644 *frT = *frB & ~BIT64(0);
3645 CR1_UPDATE(Rc);
3646 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3647
3648 0.63,6.FRT,11./,16.FRB,21.136,31.Rc:X:f::Floating Negative Absolute Value
3649 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3650 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3651 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3652 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3653 *frT = *frB | BIT64(0);
3654 CR1_UPDATE(Rc);
3655 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3656
3657
3658 #
3659 # I.4.6.5 Floating-Point Arithmetic Instructions
3660 #
3661
3662 0.63,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadd:Floating Add
3663 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3664 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3665 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3666 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3667 FPSCR_BEGIN;
3668 if (is_invalid_operation(processor, cia,
3669 *frA, *frB,
3670 fpscr_vxsnan | fpscr_vxisi,
3671 0, /*single?*/
3672 0) /*negate?*/) {
3673 invalid_arithemetic_operation(processor, cia,
3674 frT, *frA, *frB, 0,
3675 0, /*instruction_is_frsp*/
3676 0, /*instruction_is_convert_to_64bit*/
3677 0, /*instruction_is_convert_to_32bit*/
3678 0); /*single-precision*/
3679 }
3680 else {
3681 /*HACK!*/
3682 double s = *(double*)frA + *(double*)frB;
3683 *(double*)frT = s;
3684 }
3685 FPSCR_END(Rc);
3686 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3687
3688 0.59,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadds:Floating Add Single
3689 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3690 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3691 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3692 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3693 FPSCR_BEGIN;
3694 if (is_invalid_operation(processor, cia,
3695 *frA, *frB,
3696 fpscr_vxsnan | fpscr_vxisi,
3697 1, /*single?*/
3698 0) /*negate?*/) {
3699 invalid_arithemetic_operation(processor, cia,
3700 frT, *frA, *frB, 0,
3701 0, /*instruction_is_frsp*/
3702 0, /*instruction_is_convert_to_64bit*/
3703 0, /*instruction_is_convert_to_32bit*/
3704 1); /*single-precision*/
3705 }
3706 else {
3707 /*HACK!*/
3708 float s = *(double*)frA + *(double*)frB;
3709 *(double*)frT = s;
3710 }
3711 FPSCR_END(Rc);
3712 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3713
3714 0.63,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsub:Floating Subtract
3715 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3716 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3717 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3718 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3719 FPSCR_BEGIN;
3720 if (is_invalid_operation(processor, cia,
3721 *frA, *frB,
3722 fpscr_vxsnan | fpscr_vxisi,
3723 0, /*single?*/
3724 1) /*negate?*/) {
3725 invalid_arithemetic_operation(processor, cia,
3726 frT, *frA, *frB, 0,
3727 0, /*instruction_is_frsp*/
3728 0, /*instruction_is_convert_to_64bit*/
3729 0, /*instruction_is_convert_to_32bit*/
3730 0); /*single-precision*/
3731 }
3732 else {
3733 /*HACK!*/
3734 double s = *(double*)frA - *(double*)frB;
3735 *(double*)frT = s;
3736 }
3737 FPSCR_END(Rc);
3738 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3739
3740 0.59,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsubs:Floating Subtract Single
3741 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3742 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3743 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3744 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3745 FPSCR_BEGIN;
3746 if (is_invalid_operation(processor, cia,
3747 *frA, *frB,
3748 fpscr_vxsnan | fpscr_vxisi,
3749 1, /*single?*/
3750 1) /*negate?*/) {
3751 invalid_arithemetic_operation(processor, cia,
3752 frT, *frA, *frB, 0,
3753 0, /*instruction_is_frsp*/
3754 0, /*instruction_is_convert_to_64bit*/
3755 0, /*instruction_is_convert_to_32bit*/
3756 1); /*single-precision*/
3757 }
3758 else {
3759 /*HACK!*/
3760 float s = *(double*)frA - *(double*)frB;
3761 *(double*)frT = s;
3762 }
3763 FPSCR_END(Rc);
3764 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3765
3766 0.63,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmul:Floating Multiply
3767 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3768 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3769 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3770 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3771 FPSCR_BEGIN;
3772 if (is_invalid_operation(processor, cia,
3773 *frA, *frC,
3774 fpscr_vxsnan | fpscr_vximz,
3775 0, /*single?*/
3776 0) /*negate?*/) {
3777 invalid_arithemetic_operation(processor, cia,
3778 frT, *frA, 0, *frC,
3779 0, /*instruction_is_frsp*/
3780 0, /*instruction_is_convert_to_64bit*/
3781 0, /*instruction_is_convert_to_32bit*/
3782 0); /*single-precision*/
3783 }
3784 else {
3785 /*HACK!*/
3786 double s = *(double*)frA * *(double*)frC;
3787 *(double*)frT = s;
3788 }
3789 FPSCR_END(Rc);
3790 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRC_BITMASK, Rc);
3791
3792 0.59,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmuls:Floating Multiply Single
3793 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3794 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3795 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3796 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3797 FPSCR_BEGIN;
3798 if (is_invalid_operation(processor, cia,
3799 *frA, *frC,
3800 fpscr_vxsnan | fpscr_vximz,
3801 1, /*single?*/
3802 0) /*negate?*/) {
3803 invalid_arithemetic_operation(processor, cia,
3804 frT, *frA, 0, *frC,
3805 0, /*instruction_is_frsp*/
3806 0, /*instruction_is_convert_to_64bit*/
3807 0, /*instruction_is_convert_to_32bit*/
3808 1); /*single-precision*/
3809 }
3810 else {
3811 /*HACK!*/
3812 float s = *(double*)frA * *(double*)frC;
3813 *(double*)frT = s;
3814 }
3815 FPSCR_END(Rc);
3816 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRC_BITMASK, Rc);
3817
3818 0.63,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdiv:Floating Divide
3819 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 31, 31, 0
3820 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 33, 33, 0
3821 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 33, 33, 0
3822 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 32, 32, 0
3823 FPSCR_BEGIN;
3824 if (is_invalid_operation(processor, cia,
3825 *frA, *frB,
3826 fpscr_vxsnan | fpscr_vxzdz,
3827 0, /*single?*/
3828 0) /*negate?*/) {
3829 invalid_arithemetic_operation(processor, cia,
3830 frT, *frA, *frB, 0,
3831 0, /*instruction_is_frsp*/
3832 0, /*instruction_is_convert_to_64bit*/
3833 0, /*instruction_is_convert_to_32bit*/
3834 0); /*single-precision*/
3835 }
3836 else if (is_invalid_zero_divide (processor, cia,
3837 *frA, *frB,
3838 0 /*single?*/)) {
3839 invalid_zero_divide_operation (processor, cia,
3840 frT, *frA, *frB,
3841 0 /*single?*/);
3842 }
3843 else {
3844 /*HACK!*/
3845 double s = *(double*)frA / *(double*)frB;
3846 *(double*)frT = s;
3847 }
3848 FPSCR_END(Rc);
3849 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3850
3851 0.59,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdivs:Floating Divide Single
3852 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 17, 17, 0
3853 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0
3854 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0
3855 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0
3856 FPSCR_BEGIN;
3857 if (is_invalid_operation(processor, cia,
3858 *frA, *frB,
3859 fpscr_vxsnan | fpscr_vxzdz,
3860 1, /*single?*/
3861 0) /*negate?*/) {
3862 invalid_arithemetic_operation(processor, cia,
3863 frT, *frA, *frB, 0,
3864 0, /*instruction_is_frsp*/
3865 0, /*instruction_is_convert_to_64bit*/
3866 0, /*instruction_is_convert_to_32bit*/
3867 1); /*single-precision*/
3868 }
3869 else if (is_invalid_zero_divide (processor, cia,
3870 *frA, *frB,
3871 1 /*single?*/)) {
3872 invalid_zero_divide_operation (processor, cia,
3873 frT, *frA, *frB,
3874 1 /*single?*/);
3875 }
3876 else {
3877 /*HACK!*/
3878 float s = *(double*)frA / *(double*)frB;
3879 *(double*)frT = s;
3880 }
3881 FPSCR_END(Rc);
3882 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3883
3884 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f:fmadd:Floating Multiply-Add
3885 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3886 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3887 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3888 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3889 FPSCR_BEGIN;
3890 double product; /*HACK! - incorrectly loosing precision ... */
3891 /* compute the multiply */
3892 if (is_invalid_operation(processor, cia,
3893 *frA, *frC,
3894 fpscr_vxsnan | fpscr_vximz,
3895 0, /*single?*/
3896 0) /*negate?*/) {
3897 invalid_arithemetic_operation(processor, cia,
3898 (unsigned64*)&product, *frA, 0, *frC,
3899 0, /*instruction_is_frsp*/
3900 0, /*instruction_is_convert_to_64bit*/
3901 0, /*instruction_is_convert_to_32bit*/
3902 0); /*single-precision*/
3903 }
3904 else {
3905 /*HACK!*/
3906 product = *(double*)frA * *(double*)frC;
3907 }
3908 /* compute the add */
3909 if (is_invalid_operation(processor, cia,
3910 product, *frB,
3911 fpscr_vxsnan | fpscr_vxisi,
3912 0, /*single?*/
3913 0) /*negate?*/) {
3914 invalid_arithemetic_operation(processor, cia,
3915 frT, product, *frB, 0,
3916 0, /*instruction_is_frsp*/
3917 0, /*instruction_is_convert_to_64bit*/
3918 0, /*instruction_is_convert_to_32bit*/
3919 0); /*single-precision*/
3920 }
3921 else {
3922 /*HACK!*/
3923 double s = product + *(double*)frB;
3924 *(double*)frT = s;
3925 }
3926 FPSCR_END(Rc);
3927 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
3928
3929 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f::Floating Multiply-Add Single
3930 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3931 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3932 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3933 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3934 FPSCR_BEGIN;
3935 float product; /*HACK! - incorrectly loosing precision ... */
3936 /* compute the multiply */
3937 if (is_invalid_operation(processor, cia,
3938 *frA, *frC,
3939 fpscr_vxsnan | fpscr_vximz,
3940 1, /*single?*/
3941 0) /*negate?*/) {
3942 invalid_arithemetic_operation(processor, cia,
3943 (unsigned64*)&product, *frA, 0, *frC,
3944 0, /*instruction_is_frsp*/
3945 0, /*instruction_is_convert_to_64bit*/
3946 0, /*instruction_is_convert_to_32bit*/
3947 0); /*single-precision*/
3948 }
3949 else {
3950 /*HACK!*/
3951 product = *(double*)frA * *(double*)frC;
3952 }
3953 /* compute the add */
3954 if (is_invalid_operation(processor, cia,
3955 product, *frB,
3956 fpscr_vxsnan | fpscr_vxisi,
3957 1, /*single?*/
3958 0) /*negate?*/) {
3959 invalid_arithemetic_operation(processor, cia,
3960 frT, product, *frB, 0,
3961 0, /*instruction_is_frsp*/
3962 0, /*instruction_is_convert_to_64bit*/
3963 0, /*instruction_is_convert_to_32bit*/
3964 0); /*single-precision*/
3965 }
3966 else {
3967 /*HACK!*/
3968 float s = product + *(double*)frB;
3969 *(double*)frT = (double)s;
3970 }
3971 FPSCR_END(Rc);
3972 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
3973
3974 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract
3975 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3976 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3977 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3978 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3979 FPSCR_BEGIN;
3980 double product; /*HACK! - incorrectly loosing precision ... */
3981 /* compute the multiply */
3982 if (is_invalid_operation(processor, cia,
3983 *frA, *frC,
3984 fpscr_vxsnan | fpscr_vximz,
3985 0, /*single?*/
3986 0) /*negate?*/) {
3987 invalid_arithemetic_operation(processor, cia,
3988 (unsigned64*)&product, *frA, 0, *frC,
3989 0, /*instruction_is_frsp*/
3990 0, /*instruction_is_convert_to_64bit*/
3991 0, /*instruction_is_convert_to_32bit*/
3992 0); /*single-precision*/
3993 }
3994 else {
3995 /*HACK!*/
3996 product = *(double*)frA * *(double*)frC;
3997 }
3998 /* compute the subtract */
3999 if (is_invalid_operation(processor, cia,
4000 product, *frB,
4001 fpscr_vxsnan | fpscr_vxisi,
4002 0, /*single?*/
4003 0) /*negate?*/) {
4004 invalid_arithemetic_operation(processor, cia,
4005 frT, product, *frB, 0,
4006 0, /*instruction_is_frsp*/
4007 0, /*instruction_is_convert_to_64bit*/
4008 0, /*instruction_is_convert_to_32bit*/
4009 0); /*single-precision*/
4010 }
4011 else {
4012 /*HACK!*/
4013 double s = product - *(double*)frB;
4014 *(double*)frT = s;
4015 }
4016 FPSCR_END(Rc);
4017 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4018
4019 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract Single
4020 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4021 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4022 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4023 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4024 FPSCR_BEGIN;
4025 float product; /*HACK! - incorrectly loosing precision ... */
4026 /* compute the multiply */
4027 if (is_invalid_operation(processor, cia,
4028 *frA, *frC,
4029 fpscr_vxsnan | fpscr_vximz,
4030 1, /*single?*/
4031 0) /*negate?*/) {
4032 invalid_arithemetic_operation(processor, cia,
4033 (unsigned64*)&product, *frA, 0, *frC,
4034 0, /*instruction_is_frsp*/
4035 0, /*instruction_is_convert_to_64bit*/
4036 0, /*instruction_is_convert_to_32bit*/
4037 0); /*single-precision*/
4038 }
4039 else {
4040 /*HACK!*/
4041 product = *(double*)frA * *(double*)frC;
4042 }
4043 /* compute the subtract */
4044 if (is_invalid_operation(processor, cia,
4045 product, *frB,
4046 fpscr_vxsnan | fpscr_vxisi,
4047 1, /*single?*/
4048 0) /*negate?*/) {
4049 invalid_arithemetic_operation(processor, cia,
4050 frT, product, *frB, 0,
4051 0, /*instruction_is_frsp*/
4052 0, /*instruction_is_convert_to_64bit*/
4053 0, /*instruction_is_convert_to_32bit*/
4054 0); /*single-precision*/
4055 }
4056 else {
4057 /*HACK!*/
4058 float s = product - *(double*)frB;
4059 *(double*)frT = (double)s;
4060 }
4061 FPSCR_END(Rc);
4062 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4063
4064 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add
4065 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
4066 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
4067 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
4068 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4069 FPSCR_BEGIN;
4070 double product; /*HACK! - incorrectly loosing precision ... */
4071 /* compute the multiply */
4072 if (is_invalid_operation(processor, cia,
4073 *frA, *frC,
4074 fpscr_vxsnan | fpscr_vximz,
4075 0, /*single?*/
4076 0) /*negate?*/) {
4077 invalid_arithemetic_operation(processor, cia,
4078 (unsigned64*)&product, *frA, 0, *frC,
4079 0, /*instruction_is_frsp*/
4080 0, /*instruction_is_convert_to_64bit*/
4081 0, /*instruction_is_convert_to_32bit*/
4082 0); /*single-precision*/
4083 }
4084 else {
4085 /*HACK!*/
4086 product = *(double*)frA * *(double*)frC;
4087 }
4088 /* compute the add */
4089 if (is_invalid_operation(processor, cia,
4090 product, *frB,
4091 fpscr_vxsnan | fpscr_vxisi,
4092 0, /*single?*/
4093 0) /*negate?*/) {
4094 invalid_arithemetic_operation(processor, cia,
4095 frT, product, *frB, 0,
4096 0, /*instruction_is_frsp*/
4097 0, /*instruction_is_convert_to_64bit*/
4098 0, /*instruction_is_convert_to_32bit*/
4099 0); /*single-precision*/
4100 }
4101 else {
4102 /*HACK!*/
4103 double s = -(product + *(double*)frB);
4104 *(double*)frT = s;
4105 }
4106 FPSCR_END(Rc);
4107 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4108
4109 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add Single
4110 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4111 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4112 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4113 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4114 FPSCR_BEGIN;
4115 float product; /*HACK! - incorrectly loosing precision ... */
4116 /* compute the multiply */
4117 if (is_invalid_operation(processor, cia,
4118 *frA, *frC,
4119 fpscr_vxsnan | fpscr_vximz,
4120 1, /*single?*/
4121 0) /*negate?*/) {
4122 invalid_arithemetic_operation(processor, cia,
4123 (unsigned64*)&product, *frA, 0, *frC,
4124 0, /*instruction_is_frsp*/
4125 0, /*instruction_is_convert_to_64bit*/
4126 0, /*instruction_is_convert_to_32bit*/
4127 0); /*single-precision*/
4128 }
4129 else {
4130 /*HACK!*/
4131 product = *(double*)frA * *(double*)frC;
4132 }
4133 /* compute the add */
4134 if (is_invalid_operation(processor, cia,
4135 product, *frB,
4136 fpscr_vxsnan | fpscr_vxisi,
4137 1, /*single?*/
4138 0) /*negate?*/) {
4139 invalid_arithemetic_operation(processor, cia,
4140 frT, product, *frB, 0,
4141 0, /*instruction_is_frsp*/
4142 0, /*instruction_is_convert_to_64bit*/
4143 0, /*instruction_is_convert_to_32bit*/
4144 0); /*single-precision*/
4145 }
4146 else {
4147 /*HACK!*/
4148 float s = -(product + *(double*)frB);
4149 *(double*)frT = (double)s;
4150 }
4151 FPSCR_END(Rc);
4152 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4153
4154 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract
4155 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
4156 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
4157 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
4158 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4159 FPSCR_BEGIN;
4160 double product; /*HACK! - incorrectly loosing precision ... */
4161 /* compute the multiply */
4162 if (is_invalid_operation(processor, cia,
4163 *frA, *frC,
4164 fpscr_vxsnan | fpscr_vximz,
4165 0, /*single?*/
4166 0) /*negate?*/) {
4167 invalid_arithemetic_operation(processor, cia,
4168 (unsigned64*)&product, *frA, 0, *frC,
4169 0, /*instruction_is_frsp*/
4170 0, /*instruction_is_convert_to_64bit*/
4171 0, /*instruction_is_convert_to_32bit*/
4172 0); /*single-precision*/
4173 }
4174 else {
4175 /*HACK!*/
4176 product = *(double*)frA * *(double*)frC;
4177 }
4178 /* compute the subtract */
4179 if (is_invalid_operation(processor, cia,
4180 product, *frB,
4181 fpscr_vxsnan | fpscr_vxisi,
4182 0, /*single?*/
4183 0) /*negate?*/) {
4184 invalid_arithemetic_operation(processor, cia,
4185 frT, product, *frB, 0,
4186 0, /*instruction_is_frsp*/
4187 0, /*instruction_is_convert_to_64bit*/
4188 0, /*instruction_is_convert_to_32bit*/
4189 0); /*single-precision*/
4190 }
4191 else {
4192 /*HACK!*/
4193 double s = -(product - *(double*)frB);
4194 *(double*)frT = s;
4195 }
4196 FPSCR_END(Rc);
4197 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4198
4199 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract Single
4200 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4201 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4202 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4203 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4204 FPSCR_BEGIN;
4205 float product; /*HACK! - incorrectly loosing precision ... */
4206 /* compute the multiply */
4207 if (is_invalid_operation(processor, cia,
4208 *frA, *frC,
4209 fpscr_vxsnan | fpscr_vximz,
4210 1, /*single?*/
4211 0) /*negate?*/) {
4212 invalid_arithemetic_operation(processor, cia,
4213 (unsigned64*)&product, *frA, 0, *frC,
4214 0, /*instruction_is_frsp*/
4215 0, /*instruction_is_convert_to_64bit*/
4216 0, /*instruction_is_convert_to_32bit*/
4217 0); /*single-precision*/
4218 }
4219 else {
4220 /*HACK!*/
4221 product = *(double*)frA * *(double*)frC;
4222 }
4223 /* compute the subtract */
4224 if (is_invalid_operation(processor, cia,
4225 product, *frB,
4226 fpscr_vxsnan | fpscr_vxisi,
4227 1, /*single?*/
4228 0) /*negate?*/) {
4229 invalid_arithemetic_operation(processor, cia,
4230 frT, product, *frB, 0,
4231 0, /*instruction_is_frsp*/
4232 0, /*instruction_is_convert_to_64bit*/
4233 0, /*instruction_is_convert_to_32bit*/
4234 0); /*single-precision*/
4235 }
4236 else {
4237 /*HACK!*/
4238 float s = -(product - *(double*)frB);
4239 *(double*)frT = (double)s;
4240 }
4241 FPSCR_END(Rc);
4242 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4243
4244
4245 #
4246 # I.4.6.6 Floating-Point Rounding and Conversion Instructions
4247 #
4248
4249 0.63,6.FRT,11./,16.FRB,21.12,31.Rc:X:f::Floating Round to Single-Precision
4250 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4251 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4252 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4253 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4254 int sign;
4255 int exp;
4256 unsigned64 frac_grx;
4257 /***/
4258 /* split off cases for what to do */
4259 if (EXTRACTED64(*frB, 1, 11) < 897
4260 && EXTRACTED64(*frB, 1, 63) > 0) {
4261 if ((FPSCR & fpscr_ue) == 0) GOTO(Disabled_Exponent_Underflow);
4262 if ((FPSCR & fpscr_ue) != 0) GOTO(Enabled_Exponent_Underflow);
4263 }
4264 if (EXTRACTED64(*frB, 1, 11) > 1150
4265 && EXTRACTED64(*frB, 1, 11) < 2047) {
4266 if ((FPSCR & fpscr_oe) == 0) GOTO(Disabled_Exponent_Overflow);
4267 if ((FPSCR & fpscr_oe) != 0) GOTO(Enabled_Exponent_Overflow);
4268 }
4269 if (EXTRACTED64(*frB, 1, 11) > 896
4270 && EXTRACTED64(*frB, 1, 11) < 1151) GOTO(Normal_Operand);
4271 if (EXTRACTED64(*frB, 1, 63) == 0) GOTO(Zero_Operand);
4272 if (EXTRACTED64(*frB, 1, 11) == 2047) {
4273 if (EXTRACTED64(*frB, 12, 63) == 0) GOTO(Infinity_Operand);
4274 if (EXTRACTED64(*frB, 12, 12) == 1) GOTO(QNaN_Operand);
4275 if (EXTRACTED64(*frB, 12, 12) == 0
4276 && EXTRACTED64(*frB, 13, 63) > 0) GOTO(SNaN_Operand);
4277 }
4278 /**/
4279 LABEL(Disabled_Exponent_Underflow):
4280 sign = EXTRACTED64(*frB, 0, 0);
4281 if (EXTRACTED64(*frB, 1, 11) == 0) {
4282 exp = -1022;
4283 frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4284 }
4285 if (EXTRACTED64(*frB, 1, 11) > 0) {
4286 exp = EXTRACTED64(*frB, 1, 11) - 1023;
4287 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4288 }
4289 /* G|R|X == zero from above */
4290 while (exp < -126) {
4291 exp = exp - 1;
4292 frac_grx = (INSERTED64(EXTRACTED64(frac_grx, 0, 54), 1, 55)
4293 | MASKED64(frac_grx, 55, 55));
4294 }
4295 FPSCR_SET_UX(EXTRACTED64(frac_grx, 24, 55) > 0);
4296 Round_Single(processor, sign, &exp, &frac_grx);
4297 FPSCR_SET_XX(FPSCR & fpscr_fi);
4298 if (EXTRACTED64(frac_grx, 0, 52) == 0) {
4299 *frT = INSERTED64(sign, 0, 0);
4300 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
4301 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
4302 }
4303 if (EXTRACTED64(frac_grx, 0, 52) > 0) {
4304 if (EXTRACTED64(frac_grx, 0, 0) == 1) {
4305 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4306 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4307 }
4308 if (EXTRACTED64(frac_grx, 0, 0) == 0) {
4309 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_denormalized_number);
4310 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_denormalized_number);
4311 }
4312 /*Normalize_Operand:*/
4313 while (EXTRACTED64(frac_grx, 0, 0) == 0) {
4314 exp = exp - 1;
4315 frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1, 52), 0, 51);
4316 }
4317 *frT = (INSERTED64(sign, 0, 0)
4318 | INSERTED64(exp + 1023, 1, 11)
4319 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4320 }
4321 GOTO(Done);
4322 /**/
4323 LABEL(Enabled_Exponent_Underflow):
4324 FPSCR_SET_UX(1);
4325 sign = EXTRACTED64(*frB, 0, 0);
4326 if (EXTRACTED64(*frB, 1, 11) == 0) {
4327 exp = -1022;
4328 frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4329 }
4330 if (EXTRACTED64(*frB, 1, 11) > 0) {
4331 exp = EXTRACTED64(*frB, 1, 11) - 1023;
4332 frac_grx = (BIT64(0) |
4333 INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52));
4334 }
4335 /*Normalize_Operand:*/
4336 while (EXTRACTED64(frac_grx, 0, 0) == 0) {
4337 exp = exp - 1;
4338 frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1, 52), 0, 51);
4339 }
4340 Round_Single(processor, sign, &exp, &frac_grx);
4341 FPSCR_SET_XX(FPSCR & fpscr_fi);
4342 exp = exp + 192;
4343 *frT = (INSERTED64(sign, 0, 0)
4344 | INSERTED64(exp + 1023, 1, 11)
4345 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4346 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4347 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4348 GOTO(Done);
4349 /**/
4350 LABEL(Disabled_Exponent_Overflow):
4351 FPSCR_SET_OX(1);
4352 if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
4353 if (EXTRACTED64(*frB, 0, 0) == 0) {
4354 *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
4355 FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
4356 }
4357 if (EXTRACTED64(*frB, 0, 0) == 1) {
4358 *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
4359 FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
4360 }
4361 }
4362 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_zero) {
4363 if (EXTRACTED64(*frB, 0, 0) == 0) {
4364 *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
4365 FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4366 }
4367 if (EXTRACTED64(*frB, 0, 0) == 1) {
4368 *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
4369 FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4370 }
4371 }
4372 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_pos_infinity) {
4373 if (EXTRACTED64(*frB, 0, 0) == 0) {
4374 *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
4375 FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
4376 }
4377 if (EXTRACTED64(*frB, 0, 0) == 1) {
4378 *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
4379 FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4380 }
4381 }
4382 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_neg_infinity) {
4383 if (EXTRACTED64(*frB, 0, 0) == 0) {
4384 *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
4385 FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4386 }
4387 if (EXTRACTED64(*frB, 0, 0) == 1) {
4388 *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
4389 FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
4390 }
4391 }
4392 /* FPSCR[FR] <- undefined */
4393 FPSCR_SET_FI(1);
4394 FPSCR_SET_XX(1);
4395 GOTO(Done);
4396 /**/
4397 LABEL(Enabled_Exponent_Overflow):
4398 sign = EXTRACTED64(*frB, 0, 0);
4399 exp = EXTRACTED64(*frB, 1, 11) - 1023;
4400 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4401 Round_Single(processor, sign, &exp, &frac_grx);
4402 FPSCR_SET_XX(FPSCR & fpscr_fi);
4403 /**/
4404 LABEL(Enabled_Overflow):
4405 FPSCR_SET_OX(1);
4406 exp = exp - 192;
4407 *frT = (INSERTED64(sign, 0, 0)
4408 | INSERTED64(exp + 1023, 1, 11)
4409 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4410 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4411 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4412 GOTO(Done);
4413 /**/
4414 LABEL(Zero_Operand):
4415 *frT = *frB;
4416 if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
4417 if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
4418 FPSCR_SET_FR(0);
4419 FPSCR_SET_FI(0);
4420 GOTO(Done);
4421 /**/
4422 LABEL(Infinity_Operand):
4423 *frT = *frB;
4424 if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
4425 if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
4426 FPSCR_SET_FR(0);
4427 FPSCR_SET_FI(0);
4428 GOTO(Done);
4429 /**/
4430 LABEL(QNaN_Operand):
4431 *frT = INSERTED64(EXTRACTED64(*frB, 0, 34), 0, 34);
4432 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
4433 FPSCR_SET_FR(0);
4434 FPSCR_SET_FI(0);
4435 GOTO(Done);
4436 /**/
4437 LABEL(SNaN_Operand):
4438 FPSCR_OR_VX(fpscr_vxsnan);
4439 if ((FPSCR & fpscr_ve) == 0) {
4440 *frT = (MASKED64(*frB, 0, 11)
4441 | BIT64(12)
4442 | MASKED64(*frB, 13, 34));
4443 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
4444 }
4445 FPSCR_SET_FR(0);
4446 FPSCR_SET_FI(0);
4447 GOTO(Done);
4448 /**/
4449 LABEL(Normal_Operand):
4450 sign = EXTRACTED64(*frB, 0, 0);
4451 exp = EXTRACTED64(*frB, 1, 11) - 1023;
4452 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4453 Round_Single(processor, sign, &exp, &frac_grx);
4454 FPSCR_SET_XX(FPSCR & fpscr_fi);
4455 if (exp > 127 && (FPSCR & fpscr_oe) == 0) GOTO(Disabled_Exponent_Overflow);
4456 if (exp > 127 && (FPSCR & fpscr_oe) != 0) GOTO(Enabled_Overflow);
4457 *frT = (INSERTED64(sign, 0, 0)
4458 | INSERTED64(exp + 1023, 1, 11)
4459 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4460 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4461 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4462 GOTO(Done);
4463 /**/
4464 LABEL(Done):
4465 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
4466
4467
4468 0.63,6.FRT,11./,16.FRB,21.814,31.Rc:X:64,f::Floating Convert To Integer Doubleword
4469 floating_point_assist_interrupt(processor, cia);
4470
4471 0.63,6.FRT,11./,16.FRB,21.815,31.Rc:X:64,f::Floating Convert To Integer Doubleword with round towards Zero
4472 floating_point_assist_interrupt(processor, cia);
4473
4474 0.63,6.FRT,11./,16.FRB,21.14,31.Rc:X:f::Floating Convert To Integer Word
4475 floating_point_assist_interrupt(processor, cia);
4476
4477 0.63,6.FRT,11./,16.FRB,21.15,31.Rc:X:f:fctiwz:Floating Convert To Integer Word with round towards Zero
4478 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4479 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4480 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4481 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4482 FPSCR_BEGIN;
4483 convert_to_integer(processor, cia,
4484 frT, *frB,
4485 fpscr_rn_round_towards_zero, 32);
4486 FPSCR_END(Rc);
4487 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
4488
4489 0.63,6.FRT,11./,16.FRB,21.846,31.Rc:X:64,f::Floating Convert from Integer Doubleword
4490 int sign = EXTRACTED64(*frB, 0, 0);
4491 int exp = 63;
4492 unsigned64 frac = *frB;
4493 /***/
4494 if (frac == 0) GOTO(Zero_Operand);
4495 if (sign == 1) frac = ~frac + 1;
4496 while (EXTRACTED64(frac, 0, 0) == 0) {
4497 /*??? do the loop 0 times if (FRB) = max negative integer */
4498 frac = INSERTED64(EXTRACTED64(frac, 1, 63), 0, 62);
4499 exp = exp - 1;
4500 }
4501 Round_Float(processor, sign, &exp, &frac, FPSCR & fpscr_rn);
4502 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4503 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4504 *frT = (INSERTED64(sign, 0, 0)
4505 | INSERTED64(exp + 1023, 1, 11)
4506 | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
4507 GOTO(Done);
4508 /**/
4509 LABEL(Zero_Operand):
4510 FPSCR_SET_FR(0);
4511 FPSCR_SET_FI(0);
4512 FPSCR_SET_FPRF(fpscr_rf_pos_zero);
4513 *frT = 0;
4514 GOTO(Done);
4515 /**/
4516 LABEL(Done):
4517 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
4518
4519
4520 #
4521 # I.4.6.7 Floating-Point Compare Instructions
4522 #
4523
4524 0.63,6.BF,9./,11.FRA,16.FRB,21.0,31./:X:f:fcmpu:Floating Compare Unordered
4525 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4526 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4527 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4528 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4529 FPSCR_BEGIN;
4530 unsigned c;
4531 if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
4532 c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
4533 else if (is_less_than(frA, frB))
4534 c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
4535 else if (is_greater_than(frA, frB))
4536 c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
4537 else
4538 c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
4539 FPSCR_SET_FPCC(c);
4540 CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
4541 if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0))
4542 FPSCR_OR_VX(fpscr_vxsnan);
4543 FPSCR_END(0);
4544 PPC_INSN_FLOAT_CR(0, FRA_BITMASK | FRB_BITMASK, BF_BITMASK);
4545
4546 0.63,6.BF,9./,11.FRA,16.FRB,21.32,31./:X:f:fcmpo:Floating Compare Ordered
4547 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4548 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4549 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4550 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4551 FPSCR_BEGIN;
4552 unsigned c;
4553 if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
4554 c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
4555 else if (is_less_than(frA, frB))
4556 c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
4557 else if (is_greater_than(frA, frB))
4558 c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
4559 else
4560 c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
4561 FPSCR_SET_FPCC(c);
4562 CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
4563 if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0)) {
4564 FPSCR_OR_VX(fpscr_vxsnan);
4565 if ((FPSCR & fpscr_ve) == 0)
4566 FPSCR_OR_VX(fpscr_vxvc);
4567 }
4568 else if (is_QNaN(*frA, 0) || is_QNaN(*frB, 0)) {
4569 FPSCR_OR_VX(fpscr_vxvc);
4570 }
4571 FPSCR_END(0);
4572 PPC_INSN_FLOAT_CR(0, FRA_BITMASK | FRB_BITMASK, BF_BITMASK);
4573
4574
4575 #
4576 # I.4.6.8 Floating-Point Status and Control Register Instructions
4577 #
4578
4579 0.63,6.FRT,11./,16./,21.583,31.Rc:X:f::Move From FPSCR
4580 FPSCR_BEGIN;
4581 *frT = FPSCR;
4582 FPSCR_END(Rc);
4583
4584 0.63,6.BF,9./,11.BFA,14./,16./,21.64,31./:X:f::Move to Condition Register from FPSCR
4585 FPSCR_BEGIN;
4586 unsigned field = FPSCR_FIELD(BFA);
4587 CR_SET(BF, field);
4588 FPSCR_SET(BFA, 0); /* FPSCR_END fixes up FEX/VX */
4589 FPSCR_END(0);
4590
4591 0.64,6.BF,9./,11./,16.U,20./,21.134,31.Rc:X:f::Move To FPSCR Field Immediate
4592 FPSCR_BEGIN;
4593 FPSCR_SET(BF, U);
4594 FPSCR_END(Rc);
4595
4596 0.63,6./,7.FLM,15./,16.FRB,21.711,31.Rc:XFL:f::Move To FPSCR Fields
4597 FPSCR_BEGIN;
4598 int i;
4599 for (i = 0; i < 8; i++) {
4600 if ((FLM & BIT8(i))) {
4601 FPSCR &= ~MASK32(i*4, i*4+3);
4602 FPSCR |= MASKED32(*frB, i*4, i*4+3);
4603 }
4604 }
4605 FPSCR_END(Rc);
4606
4607 0.63,6.BT,11./,16./,21.70,31.Rc:X:f::Move To FPSCR Bit 0
4608 FPSCR_BEGIN;
4609 unsigned32 bit = BIT32(BT);
4610 FPSCR &= ~bit;
4611 FPSCR_END(Rc);
4612
4613 0.63,6.BT,11./,16./,21.38,31.Rc:X:f::Move To FPSCR Bit 1
4614 FPSCR_BEGIN;
4615 unsigned32 bit = BIT32(BT);
4616 if (bit & fpscr_fi)
4617 bit |= fpscr_xx;
4618 if ((bit & fpscr_vx_bits))
4619 bit |= fpscr_fx;
4620 /* note - omit vx bit */
4621 if ((bit & (fpscr_ox | fpscr_ux | fpscr_zx | fpscr_xx)))
4622 bit |= fpscr_fx;
4623 FPSCR |= bit;
4624 FPSCR_END(Rc);
4625
4626
4627 #
4628 # I.A.1.1 Floating-Point Store Instruction
4629 #
4630 0.31,6.FRS,11.RA,16.RB,21.983,31./:X:f,o::Store Floating-Point as Integer Word Indexed
4631 program_interrupt(processor, cia, optional_instruction_program_interrupt);
4632
4633 #
4634 # I.A.1.2 Floating-Point Arithmetic Instructions
4635 #
4636
4637 0.63,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f,o::Floating Square Root
4638 program_interrupt(processor, cia, optional_instruction_program_interrupt);
4639
4640 0.59,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f,o::Floating Square Root Single
4641 program_interrupt(processor, cia, optional_instruction_program_interrupt);
4642
4643 0.59,6.FRT,11./,16.FRB,21./,26.24,31.Rc:A:f,o::Floating Reciprocal Estimate Single
4644 program_interrupt(processor, cia, optional_instruction_program_interrupt);
4645
4646 0.63,6.FRT,11./,16.FRB,21./,26.26,31.Rc:A:f,o::Floating Reciprocal Square Root Estimate
4647 program_interrupt(processor, cia, optional_instruction_program_interrupt);
4648
4649 #
4650 # I.A.1.3 Floating-Point Select Instruction
4651 #
4652
4653 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.23,31.Rc:A:f,o::Floating Select
4654 *601: PPC_UNIT_BAD, PPC_UNIT_BAD, 0, 0, 0
4655 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4656 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4657 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4658 if (CURRENT_MODEL == MODEL_ppc601) {
4659 program_interrupt(processor, cia, optional_instruction_program_interrupt);
4660 } else {
4661 unsigned64 zero = 0;
4662 FPSCR_BEGIN;
4663 if (is_NaN(*frA, 0) || is_less_than (frA, &zero)) *frT = *frB;
4664 else *frT = *frC;
4665 FPSCR_END(Rc);
4666 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4667 }
4668
4669 #
4670 # II.3.2 Cache Management Instructions
4671 #
4672
4673 0.31,6./,11.RA,16.RB,21.982,31./:X::icbi:Instruction Cache Block Invalidate
4674 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4675 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4676 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4677 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
4678 /* blindly flush all instruction cache entries */
4679 #if WITH_IDECODE_CACHE_SIZE
4680 cpu_flush_icache(processor);
4681 #endif
4682 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0);
4683
4684 0.19,6./,11./,16./,21.150,31./:XL::isync:Instruction Synchronize
4685 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4686 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4687 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4688 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
4689 cpu_synchronize_context(processor, cia);
4690 PPC_INSN_INT(0, 0, 0);
4691
4692
4693 #
4694 # II.3.2.2 Data Cache Instructions
4695 #
4696
4697 0.31,6./,11.RA,16.RB,21.278,31./:X:::Data Cache Block Touch
4698 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4699 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4700 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4701 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
4702 TRACE(trace_tbd,("Data Cache Block Touch\n"));
4703 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4704
4705 0.31,6./,11.RA,16.RB,21.246,31./:X:::Data Cache Block Touch for Store
4706 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4707 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4708 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4709 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4710 TRACE(trace_tbd,("Data Cache Block Touch for Store\n"));
4711 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4712
4713 0.31,6./,11.RA,16.RB,21.1014,31./:X:::Data Cache Block set to Zero
4714 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4715 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 10, 10, 0
4716 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 10, 10, 0
4717 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4718 TRACE(trace_tbd,("Data Cache Block set to Zero\n"));
4719 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4720
4721 0.31,6./,11.RA,16.RB,21.54,31./:X:::Data Cache Block Store
4722 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4723 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
4724 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
4725 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
4726 TRACE(trace_tbd,("Data Cache Block Store\n"));
4727 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4728
4729 0.31,6./,11.RA,16.RB,21.86,31./:X:::Data Cache Block Flush
4730 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4731 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
4732 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
4733 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
4734 TRACE(trace_tbd,("Data Cache Block Flush\n"));
4735 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4736
4737 #
4738 # II.3.3 Enforce In-order Execution of I/O Instruction
4739 #
4740
4741 0.31,6./,11./,16./,21.854,31./:X::eieio:Enforce In-order Execution of I/O
4742 /* Since this model has no instruction overlap
4743 this instruction need do nothing */
4744
4745 #
4746 # II.4.1 Time Base Instructions
4747 #
4748
4749 0.31,6.RT,11.tbr,21.371,31./:XFX::mftb:Move From Time Base
4750 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
4751 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
4752 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
4753 int n = (tbr{5:9} << 5) | tbr{0:4};
4754 if (n == 268) {
4755 if (is_64bit_implementation) *rT = TB;
4756 else *rT = EXTRACTED64(TB, 32, 63);
4757 }
4758 else if (n == 269) {
4759 if (is_64bit_implementation) *rT = EXTRACTED64(TB, 0, 31);
4760 else *rT = EXTRACTED64(TB, 0, 31);
4761 }
4762 else
4763 program_interrupt(processor, cia,
4764 illegal_instruction_program_interrupt);
4765
4766
4767 #
4768 # III.2.3.1 System Linkage Instructions
4769 #
4770
4771 0.19,6./,11./,16./,21.50,31./:XL::rfi:Return From Interrupt
4772 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4773 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4774 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4775 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
4776 if (IS_PROBLEM_STATE(processor)) {
4777 program_interrupt(processor, cia,
4778 privileged_instruction_program_interrupt);
4779 }
4780 else {
4781 MSR = (MASKED(SRR1, 0, 32)
4782 | MASKED(SRR1, 37, 41)
4783 | MASKED(SRR1, 48, 63));
4784 NIA = MASKED(SRR0, 0, 61);
4785 cpu_synchronize_context(processor, cia);
4786 check_masked_interrupts(processor);
4787 }
4788
4789 #
4790 # III.3.4.1 Move to/from System Register Instructions
4791 #
4792
4793 #0.31,6.RS,11.SPR,21.467,31./:XFX:::Move To Special Purpose Register
4794 #0.31,6.RT,11.SPR,21.339,31./:XFX:::Move From Special Purpose Register
4795 0.31,6.RS,11./,16./,21.146,31./:X:::Move To Machine State Register
4796 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4797 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4798 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4799 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4800 if (IS_PROBLEM_STATE(processor))
4801 program_interrupt(processor, cia,
4802 privileged_instruction_program_interrupt);
4803 else {
4804 MSR = *rS;
4805 check_masked_interrupts(processor);
4806 }
4807
4808 0.31,6.RT,11./,16./,21.83,31./:X:::Move From Machine State Register
4809 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4810 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
4811 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
4812 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
4813 if (IS_PROBLEM_STATE(processor))
4814 program_interrupt(processor, cia,
4815 privileged_instruction_program_interrupt);
4816 else {
4817 *rT = MSR;
4818 check_masked_interrupts(processor);
4819 }
4820
4821
4822 #
4823 # III.4.11.1 Cache Management Instructions
4824 #
4825
4826 0.31,6./,11.RA,16.RB,21.470,31./:X::dcbi:Data Cache Block Invalidate
4827 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4828 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4829 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4830 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4831 if (IS_PROBLEM_STATE(processor))
4832 program_interrupt(processor, cia,
4833 privileged_instruction_program_interrupt);
4834 else
4835 TRACE(trace_tbd,("Data Cache Block Invalidate\n"));
4836
4837 #
4838 # III.4.11.2 Segment Register Manipulation Instructions
4839 #
4840
4841 0.31,6.RS,11./,12.SR,16./,21.210,31./:X:32:mtsr %SR,%RS:Move To Segment Register
4842 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4843 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4844 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4845 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4846 if (IS_PROBLEM_STATE(processor))
4847 program_interrupt(processor, cia,
4848 privileged_instruction_program_interrupt);
4849 else
4850 SEGREG(SR) = *rS;
4851
4852 0.31,6.RS,11./,16.RB,21.242,31./:X:32:mtsrin %RS,%RB:Move To Segment Register Indirect
4853 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4854 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4855 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4856 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4857 if (IS_PROBLEM_STATE(processor))
4858 program_interrupt(processor, cia,
4859 privileged_instruction_program_interrupt);
4860 else
4861 SEGREG(EXTRACTED32(*rB, 0, 3)) = *rS;
4862
4863 0.31,6.RT,11./,12.SR,16./,21.595,31./:X:32:mfsr %RT,%RS:Move From Segment Register
4864 *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
4865 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4866 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4867 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4868 if (IS_PROBLEM_STATE(processor))
4869 program_interrupt(processor, cia,
4870 privileged_instruction_program_interrupt);
4871 else
4872 *rT = SEGREG(SR);
4873
4874 0.31,6.RT,11./,16.RB,21.659,31./:X:32:mfsrin %RT,%RB:Move From Segment Register Indirect
4875 *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
4876 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4877 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4878 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4879 if (IS_PROBLEM_STATE(processor))
4880 program_interrupt(processor, cia,
4881 privileged_instruction_program_interrupt);
4882 else
4883 *rT = SEGREG(EXTRACTED32(*rB, 0, 3));
4884
4885
4886 #
4887 # III.4.11.3 Lookaside Buffer Management Instructions (Optional)
4888 #
4889
4890 0.31,6./,11./,16.RB,21.434,31./:X:64::SLB Invalidate Entry
4891
4892 0.31,6./,11./,16./,21.498,31./:X:64::SLB Invalidate All
4893
4894 0.31,6./,11./,16.RB,21.306,31./:X:::TLB Invalidate Entry
4895 if (IS_PROBLEM_STATE(processor))
4896 program_interrupt(processor, cia,
4897 privileged_instruction_program_interrupt);
4898 else {
4899 int nr = 0;
4900 cpu *proc;
4901 while (1) {
4902 proc = psim_cpu(cpu_system(processor), nr);
4903 if (proc == NULL) break;
4904 cpu_page_tlb_invalidate_entry(proc, *rB);
4905 nr++;
4906 }
4907 }
4908
4909 0.31,6./,11./,16./,21.370,31./:X:::TLB Invalidate All
4910 if (IS_PROBLEM_STATE(processor))
4911 program_interrupt(processor, cia,
4912 privileged_instruction_program_interrupt);
4913 else {
4914 int nr = 0;
4915 cpu *proc;
4916 while (1) {
4917 proc = psim_cpu(cpu_system(processor), nr);
4918 if (proc == NULL) break;
4919 cpu_page_tlb_invalidate_all(proc);
4920 nr++;
4921 }
4922 }
4923
4924 0.31,6./,11./,16./,21.566,31./:X:::TLB Synchronize
4925 /* nothing happens here - always in sync */
4926
4927 #
4928 # III.A.1.2 External Access Instructions
4929 #
4930
4931 0.31,6.RT,11.RA,16.RB,21.310,31./:X:earwax::External Control In Word Indexed
4932
4933 0.31,6.RS,11.RA,16.RB,21.438,31./:X:earwax::External Control Out Word Indexed