New simulator changes from Andrew
[deliverable/binutils-gdb.git] / sim / ppc / ppc-instructions
1 #
2 # This file is part of the program psim.
3 #
4 # Copyright (C) 1994-1996, 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(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK); \
50 else \
51 ppc_insn_int_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, 1 << 0); \
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 unavilable";
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 enum { start, finish, Infinity_Operand, SNaN_Operand, QNaN_Operand, Large_Operand, Done } label = start;
1113 while (label != finish) switch (label) {
1114 case finish:
1115 error("Unhandled switch\n");
1116 case start:
1117 if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 63) == 0)
1118 { label = Infinity_Operand; break; }
1119 if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 0)
1120 { label = SNaN_Operand; break; }
1121 if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 1)
1122 { label = QNaN_Operand; break; }
1123 if (EXTRACTED64(frb, 1, 11) > 1086) { label = Large_Operand; break; }
1124 if (EXTRACTED64(frb, 1, 11) > 0) exp = EXTRACTED64(frb, 1, 11) - 1023;
1125 if (EXTRACTED64(frb, 1, 11) == 0) exp = -1022;
1126 if (EXTRACTED64(frb, 1, 11) > 0) { /* normal */
1127 frac = BIT64(1) | INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
1128 frac64 = 0;
1129 }
1130 if (EXTRACTED64(frb, 1, 11) == 0) { /* denorm */
1131 frac = INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
1132 frac64 = 0;
1133 }
1134 gbit = 0, rbit = 0, xbit = 0;
1135 for (i = 1; i <= 63 - exp; i++) {
1136 xbit = rbit | xbit;
1137 rbit = gbit;
1138 gbit = frac64;
1139 frac64 = EXTRACTED64(frac, 63, 63);
1140 frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63);
1141 }
1142 Round_Integer(processor, sign, &frac, &frac64, gbit, rbit, xbit, round_mode);
1143 if (sign == 1) { /* frac[0:64] = ~frac[0:64] + 1 */
1144 frac = ~frac;
1145 frac64 ^= 1;
1146 frac += (frac64 ? 1 : 0);
1147 frac64 = (frac64 + 1) & 0x1;
1148 }
1149 if (tgt_precision == 32 /* can ignore frac64 in compare */
1150 && (signed64)frac > (signed64)MASK64(33+1, 63)/*2^31-1 >>1*/)
1151 { label = Large_Operand; break; }
1152 if (tgt_precision == 64 /* can ignore frac64 in compare */
1153 && (signed64)frac > (signed64)MASK64(1+1, 63)/*2^63-1 >>1*/)
1154 { label = Large_Operand; break; }
1155 if (tgt_precision == 32 /* can ignore frac64 in compare */
1156 && (signed64)frac < (signed64)MASK64(0, 32+1)/*-2^31 >>1*/)
1157 { label = Large_Operand; break; }
1158 if (tgt_precision == 64 /* can ignore frac64 in compare */
1159 && (signed64)frac < (signed64)MASK64(0, 0+1)/*-2^63 >>1*/)
1160 { label = Large_Operand; break; }
1161 FPSCR_SET_XX(FPSCR & fpscr_fi);
1162 if (tgt_precision == 32)
1163 *frt = MASKED64(*frt, 0, 31) | (EXTRACTED64(frac, 33, 63) << 1) | frac64;
1164 if (tgt_precision == 64)
1165 *frt = (EXTRACTED64(frac, 1, 63) << 1) | frac64;
1166 /*FPSCR[fprf] = undefined */
1167 { label = Done; break; }
1168 /**/
1169 case Infinity_Operand:
1170 FPSCR_SET_FR(0);
1171 FPSCR_SET_FI(0);
1172 FPSCR_OR_VX(fpscr_vxcvi);
1173 if ((FPSCR & fpscr_ve) == 0) {
1174 if (tgt_precision == 32) {
1175 if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7FFFFFFF;
1176 if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1177 }
1178 else {
1179 if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/
1180 if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
1181 }
1182 /* FPSCR[FPRF] = undefined */
1183 }
1184 { label = Done; break; }
1185 /**/
1186 case SNaN_Operand:
1187 FPSCR_SET_FR(0);
1188 FPSCR_SET_FI(0);
1189 FPSCR_OR_VX(fpscr_vxsnan | fpscr_vxcvi);
1190 if ((FPSCR & fpscr_ve) == 0) {
1191 if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1192 if (tgt_precision == 64) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
1193 /* FPSCR[fprf] = undefined */
1194 }
1195 { label = Done; break; }
1196 /**/
1197 case QNaN_Operand:
1198 FPSCR_SET_FR(0);
1199 FPSCR_SET_FI(0);
1200 FPSCR_OR_VX(fpscr_vxcvi);
1201 if ((FPSCR & fpscr_ve) == 0) {
1202 if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1203 if (tgt_precision == 64) *frt = BIT64(0);/*0x8000_0000_0000_0000*/
1204 /* FPSCR[fprf] = undefined */
1205 }
1206 { label = Done; break; }
1207 /**/
1208 case Large_Operand:
1209 FPSCR_SET_FR(0);
1210 FPSCR_SET_FI(0);
1211 FPSCR_OR_VX(fpscr_vxcvi);
1212 if ((FPSCR & fpscr_ve) == 0) {
1213 if (tgt_precision == 32) {
1214 if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7fffffff;
1215 if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1216 }
1217 else {
1218 if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/
1219 if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
1220 }
1221 /* FPSCR[fprf] = undefined */
1222 }
1223 /**/
1224 case Done:
1225 { label = finish; break; }
1226 }
1227
1228
1229 # extract out raw fields of a FP number
1230 int::function::sign:unsigned64 FRS
1231 return (MASKED64(FRS, 0, 0)
1232 ? -1
1233 : 1);
1234 int::function::biased_exp:unsigned64 frs, int single
1235 if (single)
1236 return EXTRACTED64(frs, 1, 8);
1237 else
1238 return EXTRACTED64(frs, 1, 11);
1239 unsigned64::function::fraction:unsigned64 frs, int single
1240 if (single)
1241 return EXTRACTED64(frs, 9, 31);
1242 else
1243 return EXTRACTED64(frs, 12, 63);
1244
1245 # a number?, each of the below return +1 or -1 (based on sign bit)
1246 # if true.
1247 int::function::is_nor:unsigned64 frs, int single
1248 int exp = biased_exp(frs, single);
1249 return (exp >= 1
1250 && exp <= (single ? 254 : 2046));
1251 int::function::is_zero:unsigned64 FRS
1252 return (MASKED64(FRS, 1, 63) == 0
1253 ? sign(FRS)
1254 : 0);
1255 int::function::is_den:unsigned64 frs, int single
1256 int exp = biased_exp(frs, single);
1257 unsigned64 frac = fraction(frs, single);
1258 return (exp == 0 && frac != 0
1259 ? sign(frs)
1260 : 0);
1261 int::function::is_inf:unsigned64 frs, int single
1262 int exp = biased_exp(frs, single);
1263 int frac = fraction(frs, single);
1264 return (exp == (single ? 255 : 2047) && frac == 0
1265 ? sign(frs)
1266 : 0);
1267 int::function::is_NaN:unsigned64 frs, int single
1268 int exp = biased_exp(frs, single);
1269 int frac = fraction(frs, single);
1270 return (exp == (single ? 255 : 2047) && frac != 0
1271 ? sign(frs)
1272 : 0);
1273 int::function::is_SNaN:unsigned64 frs, int single
1274 return (is_NaN(frs, single)
1275 && !(frs & (single ? MASK64(9, 9) : MASK64(12, 12)))
1276 ? sign(frs)
1277 : 0);
1278 int::function::is_QNaN:unsigned64 frs, int single
1279 return (is_NaN(frs, single) && !is_SNaN(frs, single));
1280 int::function::is_less_than:unsigned64 *fra, unsigned64 *frb
1281 return *(double*)fra < *(double*)frb;
1282 int::function::is_greater_than:unsigned64 *fra, unsigned64 *frb
1283 return *(double*)fra > *(double*)frb;
1284 int::function::is_equan_to:unsigned64 *fra, unsigned64 *frb
1285 return *(double*)fra == *(double*)frb;
1286
1287
1288 # which quiet nan should become the result
1289 unsigned64::function::select_qnan:unsigned64 fra, unsigned64 frb, unsigned64 frc, int instruction_is_frsp, int generate_qnan, int single
1290 unsigned64 frt = 0;
1291 if (is_NaN(fra, single))
1292 frt = fra;
1293 else if (is_NaN(frb, single))
1294 if (instruction_is_frsp)
1295 frt = MASKED64(frb, 0, 34);
1296 else
1297 frt = frb;
1298 else if (is_NaN(frc, single))
1299 frt = frc;
1300 else if (generate_qnan)
1301 frt = MASK64(1, 12); /* 0x7FF8_0000_0000_0000 */
1302 else
1303 error("select_qnan - default reached\n");
1304 return frt;
1305
1306
1307 # detect invalid operation
1308 int::function::is_invalid_operation:cpu *processor, unsigned_word cia, unsigned64 fra, unsigned64 frb, fpscreg check, int single, int negate
1309 int fail = 0;
1310 if ((check & fpscr_vxsnan)
1311 && (is_SNaN(fra, single) || is_SNaN(frb, single))) {
1312 FPSCR_OR_VX(fpscr_vxsnan);
1313 fail = 1;
1314 }
1315 if ((check & fpscr_vxisi)
1316 && (is_inf(fra, single) && is_inf(frb, single))
1317 && ((negate && sign(fra) != sign(frb))
1318 || (!negate && sign(fra) == sign(frb)))) {
1319 /*FIXME: don't handle inf-inf VS inf+-inf */
1320 FPSCR_OR_VX(fpscr_vxisi);
1321 fail = 1;
1322 }
1323 if ((check & fpscr_vxidi)
1324 && (is_inf(fra, single) && is_inf(frb, single))) {
1325 FPSCR_OR_VX(fpscr_vxidi);
1326 fail = 1;
1327 }
1328 if ((check & fpscr_vxzdz)
1329 && (is_zero(fra) && is_zero(frb))) {
1330 FPSCR_OR_VX(fpscr_vxzdz);
1331 fail = 1;
1332 }
1333 if ((check & fpscr_vximz)
1334 && (is_zero(fra) && is_inf(frb, single))) {
1335 FPSCR_OR_VX(fpscr_vximz);
1336 fail = 1;
1337 }
1338 if ((check & fpscr_vxvc)
1339 && (is_NaN(fra, single) || is_NaN(frb, single))) {
1340 FPSCR_OR_VX(fpscr_vxvc);
1341 fail = 1;
1342 }
1343 if ((check & fpscr_vxsoft)) {
1344 FPSCR_OR_VX(fpscr_vxsoft);
1345 fail = 1;
1346 }
1347 if ((check & fpscr_vxsqrt)
1348 && sign(fra) < 0) {
1349 FPSCR_OR_VX(fpscr_vxsqrt);
1350 fail = 1;
1351 }
1352 /* if ((check && fpscr_vxcvi) {
1353 && (is_inf(fra, single) || is_NaN(fra, single) || is_large(fra, single)))
1354 FPSCR_OR_VX(fpscr_vxcvi);
1355 fail = 1;
1356 }
1357 */
1358 return fail;
1359
1360
1361
1362
1363
1364 # handle case of invalid operation
1365 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
1366 if (FPSCR & fpscr_ve) {
1367 /* invalid operation exception enabled */
1368 /* FRT unchaged */
1369 FPSCR_SET_FR(0);
1370 FPSCR_SET_FI(0);
1371 /* fpscr_FPRF unchanged */
1372 }
1373 else {
1374 /* invalid operation exception disabled */
1375 if (instruction_is_convert_to_64bit) {
1376 error("oopsi");
1377 }
1378 else if (instruction_is_convert_to_32bit) {
1379 error("oopsi");
1380 }
1381 else { /* arrith, frsp */
1382 *frt = select_qnan(fra, frb, frc,
1383 instruction_is_frsp, 0/*generate*/, single);
1384 FPSCR_SET_FR(0);
1385 FPSCR_SET_FI(0);
1386 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
1387 }
1388 }
1389
1390
1391
1392
1393 #
1394 # 0.0.0.0 Illegal instruction used for kernel mode emulation
1395 #
1396 0.0,6./,11./,16./,21./,31.1:X:::instruction_call
1397 if (!os_emul_instruction_call(processor, cia, real_addr(cia, 1)))
1398 program_interrupt(processor, cia,
1399 illegal_instruction_program_interrupt);
1400
1401 #
1402 # I.2.4.1 Branch Instructions
1403 #
1404 0.18,6.LI,30.AA,31.LK:I:::Branch
1405 *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1406 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1407 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1408 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1409 if (AA) NIA = IEA(EXTS(LI_0b00));
1410 else NIA = IEA(CIA + EXTS(LI_0b00));
1411 if (LK) LR = (spreg)CIA+4;
1412 if (CURRENT_MODEL_ISSUE > 0)
1413 model_branches(cpu_model(processor), 1, -1);
1414
1415 0.16,6.BO,11.BI,16.BD,30.AA,31.LK:B:::Branch Conditional
1416 *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1417 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1418 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1419 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1420 int M, ctr_ok, cond_ok, succeed;
1421 if (CURRENT_MODEL_ISSUE > 0 && ! BO{0})
1422 model_wait_for_cr(cpu_model(processor), BIT32_BI);
1423 if (is_64bit_implementation && is_64bit_mode) M = 0;
1424 else M = 32;
1425 if (!BO{2}) CTR = CTR - 1;
1426 ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != (BO{3}));
1427 cond_ok = BO{0} || ((CR{BI}) == (BO{1}));
1428 if (ctr_ok && cond_ok) {
1429 if (AA) NIA = IEA(EXTS(BD_0b00));
1430 else NIA = IEA(CIA + EXTS(BD_0b00));
1431 succeed = 1;
1432 }
1433 else
1434 succeed = 0;
1435 if (LK) LR = (spreg)IEA(CIA + 4);
1436 if (CURRENT_MODEL_ISSUE > 0)
1437 model_branches(cpu_model(processor), succeed, BO);
1438 if (! BO{0}) {
1439 int reverse;
1440 if (BO{4}) { /* branch prediction bit set, reverse sense of test */
1441 reverse = EXTS(BD_0b00) < 0;
1442 } else { /* branch prediction bit not set */
1443 reverse = EXTS(BD_0b00) >= 0;
1444 }
1445 if (CURRENT_MODEL_ISSUE > 0)
1446 model_branch_predict(cpu_model(processor), reverse ? !succeed : succeed);
1447 }
1448
1449 0.19,6.BO,11.BI,16./,21.16,31.LK:XL:::Branch Conditional to Link Register
1450 *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1451 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1452 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1453 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1454 int M, ctr_ok, cond_ok, succeed;
1455 if (is_64bit_implementation && is_64bit_mode) M = 0;
1456 else M = 32;
1457 if (CURRENT_MODEL_ISSUE > 0 && ! BO{0})
1458 model_wait_for_cr(cpu_model(processor), BIT32_BI);
1459 if (!BO{2}) CTR = CTR - 1;
1460 ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != BO{3});
1461 cond_ok = BO{0} || (CR{BI} == BO{1});
1462 if (ctr_ok && cond_ok) {
1463 NIA = IEA(LR_0b00);
1464 succeed = 1;
1465 }
1466 else
1467 succeed = 0;
1468 if (LK) LR = (spreg)IEA(CIA + 4);
1469 if (CURRENT_MODEL_ISSUE > 0) {
1470 model_branches(cpu_model(processor), succeed, BO);
1471 if (! BO{0})
1472 model_branch_predict(cpu_model(processor), BO{4} ? !succeed : succeed);
1473 }
1474
1475 0.19,6.BO,11.BI,16./,21.528,31.LK:XL:::Branch Conditional to Count Register
1476 *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1477 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1478 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1479 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1480 int cond_ok, succeed;
1481 if (CURRENT_MODEL_ISSUE > 0 && ! BO{0})
1482 model_wait_for_cr(cpu_model(processor), BIT32_BI);
1483 cond_ok = BO{0} || (CR{BI} == BO{1});
1484 if (cond_ok) {
1485 NIA = IEA(CTR_0b00);
1486 succeed = 1;
1487 }
1488 else
1489 succeed = 0;
1490 if (LK) LR = (spreg)IEA(CIA + 4);
1491 if (CURRENT_MODEL_ISSUE > 0) {
1492 model_branches(cpu_model(processor), succeed, BO);
1493 if (! BO{0})
1494 model_branch_predict(cpu_model(processor), BO{4} ? !succeed : succeed);
1495 }
1496
1497 #
1498 # I.2.4.2 System Call Instruction
1499 #
1500 0.17,6./,11./,16./,30.1,31./:SC:::System Call
1501 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1502 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
1503 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
1504 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1505 if (CURRENT_MODEL_ISSUE > 0)
1506 model_serialize(MY_INDEX, cpu_model(processor));
1507 system_call_interrupt(processor, cia);
1508
1509 #
1510 # I.2.4.3 Condition Register Logical Instructions
1511 #
1512 0.19,6.BT,11.BA,16.BB,21.257,31./:XL::crand:Condition Register AND
1513 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1514 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1515 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1516 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1517 BLIT32(CR, BT, CR{BA} && CR{BB});
1518 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1519
1520 0.19,6.BT,11.BA,16.BB,21.449,31./:XL::cror:Condition Register OR
1521 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1522 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1523 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1524 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1525 BLIT32(CR, BT, CR{BA} || CR{BB});
1526 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1527
1528 0.19,6.BT,11.BA,16.BB,21.193,31./:XL::crxor:Condition Register XOR
1529 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1530 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1531 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1532 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1533 BLIT32(CR, BT, CR{BA} != CR{BB});
1534 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1535
1536 0.19,6.BT,11.BA,16.BB,21.225,31./:XL::crnand:Condition Register NAND
1537 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1538 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1539 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1540 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1541 BLIT32(CR, BT, !(CR{BA} && CR{BB}));
1542 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1543
1544 0.19,6.BT,11.BA,16.BB,21.33,31./:XL::crnor:Condition Register NOR
1545 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1546 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1547 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1548 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1549 BLIT32(CR, BT, !(CR{BA} || CR{BB}));
1550 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1551
1552 0.19,6.BT,11.BA,16.BB,21.289,31./:XL::creqv:Condition Register Equivalent
1553 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1554 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1555 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1556 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1557 BLIT32(CR, BT, CR{BA} == CR{BB});
1558 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1559
1560 0.19,6.BT,11.BA,16.BB,21.129,31./:XL::crandc:Condition Register AND with Complement
1561 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1562 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1563 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1564 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1565 BLIT32(CR, BT, CR{BA} && !CR{BB});
1566 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1567
1568 0.19,6.BT,11.BA,16.BB,21.417,31./:XL::crorc:Condition Register OR with Complement
1569 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1570 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1571 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1572 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1573 BLIT32(CR, BT, CR{BA} || !CR{BB});
1574 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1575
1576 #
1577 # I.2.4.4 Condition Register Field Instruction
1578 #
1579 0.19,6.BF,9./,11.BFA,14./,16./,21.0,31./:XL:::Move Condition Register Field
1580 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1581 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1582 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1583 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1584 MBLIT32(CR, 4*BF, 4*BF+3, EXTRACTED32(CR, 4*BFA, 4*BFA+3));
1585 PPC_INSN_CR(BF_BITMASK, 1 << BFA);
1586
1587
1588 #
1589 # I.3.3.2 Fixed-Point Load Instructions
1590 #
1591
1592 0.34,6.RT,11.RA,16.D:D:::Load Byte and Zero
1593 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1594 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1595 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1596 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1597 unsigned_word b;
1598 unsigned_word EA;
1599 if (RA == 0) b = 0;
1600 else b = *rA;
1601 EA = b + EXTS(D);
1602 *rT = MEM(unsigned, EA, 1);
1603 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
1604
1605
1606 0.31,6.RT,11.RA,16.RB,21.87,31./:X:::Load Byte and Zero Indexed
1607 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1608 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1609 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1610 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1611 unsigned_word b;
1612 unsigned_word EA;
1613 if (RA == 0) b = 0;
1614 else b = *rA;
1615 EA = b + *rB;
1616 *rT = MEM(unsigned, EA, 1);
1617 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
1618
1619 0.35,6.RT,11.RA,16.D:D:::Load Byte and Zero with Update
1620 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1621 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1622 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1623 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1624 unsigned_word EA;
1625 if (RA == 0 || RA == RT)
1626 program_interrupt(processor, cia,
1627 illegal_instruction_program_interrupt);
1628 EA = *rA + EXTS(D);
1629 *rT = MEM(unsigned, EA, 1);
1630 *rA = EA;
1631 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK, 0);
1632
1633 0.31,6.RT,11.RA,16.RB,21.119,31./:X:::Load Byte and Zero with Update Indexed
1634 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1635 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1636 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1637 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1638 unsigned_word EA;
1639 if (RA == 0 || RA == RT)
1640 program_interrupt(processor, cia,
1641 illegal_instruction_program_interrupt);
1642 EA = *rA + *rB;
1643 *rT = MEM(unsigned, EA, 1);
1644 *rA = EA;
1645 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK | RB_BITMASK, 0);
1646
1647 0.40,6.RT,11.RA,16.D:D:::Load Halfword and Zero
1648 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1649 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1650 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1651 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1652 unsigned_word b;
1653 unsigned_word EA;
1654 if (RA == 0) b = 0;
1655 else b = *rA;
1656 EA = b + EXTS(D);
1657 *rT = MEM(unsigned, EA, 2);
1658 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
1659
1660 0.31,6.RT,11.RA,16.RB,21.279,31./:X:::Load Halfword and Zero Indexed
1661 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1662 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1663 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1664 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1665 unsigned_word b;
1666 unsigned_word EA;
1667 if (RA == 0) b = 0;
1668 else b = *rA;
1669 EA = b + *rB;
1670 *rT = MEM(unsigned, EA, 2);
1671 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
1672
1673 0.41,6.RT,11.RA,16.D:D:::Load Halfword and Zero with Update
1674 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1675 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1676 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1677 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1678 unsigned_word EA;
1679 if (RA == 0 || RA == RT)
1680 program_interrupt(processor, cia,
1681 illegal_instruction_program_interrupt);
1682 EA = *rA + EXTS(D);
1683 *rT = MEM(unsigned, EA, 2);
1684 *rA = EA;
1685 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK, 0);
1686
1687 0.31,6.RT,11.RA,16.RB,21.311,31./:X:::Load Halfword and Zero with Update Indexed
1688 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1689 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1690 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1691 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1692 unsigned_word EA;
1693 if (RA == 0 || RA == RT)
1694 program_interrupt(processor, cia,
1695 illegal_instruction_program_interrupt);
1696 EA = *rA + *rB;
1697 *rT = MEM(unsigned, EA, 2);
1698 *rA = EA;
1699 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK | RB_BITMASK, 0);
1700
1701 0.42,6.RT,11.RA,16.D:D:::Load Halfword Algebraic
1702 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1703 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1704 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1705 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1706 unsigned_word b;
1707 unsigned_word EA;
1708 if (RA == 0) b = 0;
1709 else b = *rA;
1710 EA = b + EXTS(D);
1711 *rT = MEM(signed, EA, 2);
1712 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
1713
1714 0.31,6.RT,11.RA,16.RB,21.343,31./:X:::Load Halfword Algebraic Indexed
1715 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1716 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1717 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1718 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1719 unsigned_word b;
1720 unsigned_word EA;
1721 if (RA == 0) b = 0;
1722 else b = *rA;
1723 EA = b + *rB;
1724 *rT = MEM(signed, EA, 2);
1725 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
1726
1727 0.43,6.RT,11.RA,16.D:D:::Load Halfword Algebraic with Update
1728 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1729 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1730 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1731 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1732 unsigned_word EA;
1733 if (RA == 0 || RA == RT)
1734 program_interrupt(processor, cia,
1735 illegal_instruction_program_interrupt);
1736 EA = *rA + EXTS(D);
1737 *rT = MEM(signed, EA, 2);
1738 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK, 0);
1739
1740 0.31,6.RT,11.RA,16.RB,21.375,31./:X:::Load Halfword Algebraic with Update Indexed
1741 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1742 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1743 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1744 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1745 unsigned_word EA;
1746 if (RA == 0 || RA == RT)
1747 program_interrupt(processor, cia,
1748 illegal_instruction_program_interrupt);
1749 EA = *rA + *rB;
1750 *rT = MEM(signed, EA, 2);
1751 *rA = EA;
1752 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK | RB_BITMASK, 0);
1753
1754 0.32,6.RT,11.RA,16.D:D:::Load Word and Zero
1755 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1756 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1757 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1758 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1759 unsigned_word b;
1760 unsigned_word EA;
1761 if (RA == 0) b = 0;
1762 else b = *rA;
1763 EA = b + EXTS(D);
1764 *rT = MEM(unsigned, EA, 4);
1765 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
1766
1767 0.31,6.RT,11.RA,16.RB,21.23,31./:X:::Load Word and Zero Indexed
1768 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1769 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1770 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1771 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1772 unsigned_word b;
1773 unsigned_word EA;
1774 if (RA == 0) b = 0;
1775 else b = *rA;
1776 EA = b + *rB;
1777 *rT = MEM(unsigned, EA, 4);
1778 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
1779
1780 0.33,6.RT,11.RA,16.D:D:::Load Word and Zero with Update
1781 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1782 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1783 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1784 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1785 unsigned_word EA;
1786 if (RA == 0 || RA == RT)
1787 program_interrupt(processor, cia,
1788 illegal_instruction_program_interrupt);
1789 EA = *rA + EXTS(D);
1790 *rT = MEM(unsigned, EA, 4);
1791 *rA = EA;
1792 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK, 0);
1793
1794 0.31,6.RT,11.RA,16.RB,21.55,31./:X:::Load Word and Zero with Update Indexed
1795 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1796 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1797 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1798 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1799 unsigned_word EA;
1800 if (RA == 0 || RA == RT)
1801 program_interrupt(processor, cia,
1802 illegal_instruction_program_interrupt);
1803 EA = *rA + *rB;
1804 *rT = MEM(unsigned, EA, 4);
1805 *rA = EA;
1806 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK | RB_BITMASK, 0);
1807
1808 0.58,6.RT,11.RA,16.DS,30.2:DS:64::Load Word Algebraic
1809 # unsigned_word b;
1810 # unsigned_word EA;
1811 # if (RA == 0) b = 0;
1812 # else b = *rA;
1813 # EA = b + EXTS(DS_0b00);
1814 # *rT = MEM(signed, EA, 4);
1815
1816 0.31,6.RT,11.RA,16.RB,21.341,31./:X:64::Load Word Algebraic Indexed
1817 # unsigned_word b;
1818 # unsigned_word EA;
1819 # if (RA == 0) b = 0;
1820 # else b = *rA;
1821 # EA = b + *rB;;
1822 # *rT = MEM(signed, EA, 4);
1823
1824 0.31,6.RT,11.RA,16.RB,21.373,31./:X:64::Load Word Algebraic with Update Indexed
1825 # unsigned_word EA;
1826 # if (RA == 0 || RA == RT)
1827 # program_interrupt(processor, cia
1828 # illegal_instruction_program_interrupt);
1829 # EA = *rA + *rB;
1830 # *rT = MEM(signed, EA, 4);
1831 # *rA = EA;
1832
1833 0.58,6.RT,11.RA,16.DS,30.0:DS:64::Load Doubleword
1834 # unsigned_word b;
1835 # unsigned_word EA;
1836 # if (RA == 0) b = 0;
1837 # else b = *rA;
1838 # EA = b + EXTS(DS_0b00);
1839 # *rT = MEM(unsigned, EA, 8);
1840
1841 0.31,6.RT,11.RA,16.RB,21.21,31./:X:64::Load Doubleword Indexed
1842 # unsigned_word b;
1843 # unsigned_word EA;
1844 # if (RA == 0) b = 0;
1845 # else b = *rA;
1846 # EA = b + *rB;
1847 # *rT = MEM(unsigned, EA, 8);
1848
1849 0.58,6.RT,11.RA,16.DS,30.1:DS:64::Load Doubleword with Update
1850 # unsigned_word EA;
1851 # if (RA == 0 || RA == RT)
1852 # program_interrupt(processor, cia
1853 # illegal_instruction_program_interrupt);
1854 # EA = *rA + EXTS(DS_0b00);
1855 # *rT = MEM(unsigned, EA, 8);
1856 # *rA = EA;
1857
1858 0.31,6.RT,11.RA,16.RB,21.53,31./:DS:64::Load Doubleword with Update Indexed
1859 # unsigned_word EA;
1860 # if (RA == 0 || RA == RT)
1861 # program_interrupt(processor, cia
1862 # illegal_instruction_program_interrupt);
1863 # EA = *rA + *rB;
1864 # *rT = MEM(unsigned, EA, 8);
1865 # *rA = EA;
1866
1867
1868
1869 #
1870 # I.3.3.3 Fixed-Point Store Instructions
1871 #
1872
1873 0.38,6.RS,11.RA,16.D:D:::Store Byte
1874 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1875 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1876 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1877 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1878 unsigned_word b;
1879 unsigned_word EA;
1880 if (RA == 0) b = 0;
1881 else b = *rA;
1882 EA = b + EXTS(D);
1883 STORE(EA, 1, *rS);
1884 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RS_BITMASK, 0);
1885
1886 0.31,6.RS,11.RA,16.RB,21.215,31./:X:::Store Byte Indexed
1887 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1888 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1889 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1890 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1891 unsigned_word b;
1892 unsigned_word EA;
1893 if (RA == 0) b = 0;
1894 else b = *rA;
1895 EA = b + *rB;
1896 STORE(EA, 1, *rS);
1897 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
1898
1899 0.39,6.RS,11.RA,16.D:D:::Store Byte with Update
1900 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1901 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1902 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1903 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1904 unsigned_word EA;
1905 if (RA == 0)
1906 program_interrupt(processor, cia,
1907 illegal_instruction_program_interrupt);
1908 EA = *rA + EXTS(D);
1909 STORE(EA, 1, *rS);
1910 *rA = EA;
1911 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RS_BITMASK, 0);
1912
1913 0.31,6.RS,11.RA,16.RB,21.247,31./:X:::Store Byte with Update Indexed
1914 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1915 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1916 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1917 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1918 unsigned_word EA;
1919 if (RA == 0)
1920 program_interrupt(processor, cia,
1921 illegal_instruction_program_interrupt);
1922 EA = *rA + *rB;
1923 STORE(EA, 1, *rS);
1924 *rA = EA;
1925 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RB_BITMASK | RS_BITMASK, 0);
1926
1927 0.44,6.RS,11.RA,16.D:D:::Store Half Word
1928 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1929 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1930 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1931 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1932 unsigned_word b;
1933 unsigned_word EA;
1934 if (RA == 0) b = 0;
1935 else b = *rA;
1936 EA = b + EXTS(D);
1937 STORE(EA, 2, *rS);
1938 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RS_BITMASK, 0);
1939
1940 0.31,6.RS,11.RA,16.RB,21.407,31./:X:::Store Half Word Indexed
1941 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1942 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1943 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1944 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1945 unsigned_word b;
1946 unsigned_word EA;
1947 if (RA == 0) b = 0;
1948 else b = *rA;
1949 EA = b + *rB;
1950 STORE(EA, 2, *rS);
1951 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
1952
1953 0.45,6.RS,11.RA,16.D:D:::Store Half Word with Update
1954 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1955 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1956 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1957 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1958 unsigned_word EA;
1959 if (RA == 0)
1960 program_interrupt(processor, cia,
1961 illegal_instruction_program_interrupt);
1962 EA = *rA + EXTS(D);
1963 STORE(EA, 2, *rS);
1964 *rA = EA;
1965 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RS_BITMASK, 0);
1966
1967 0.31,6.RS,11.RA,16.RB,21.439,31./:X:::Store Half Word with Update Indexed
1968 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1969 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1970 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1971 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1972 unsigned_word EA;
1973 if (RA == 0)
1974 program_interrupt(processor, cia,
1975 illegal_instruction_program_interrupt);
1976 EA = *rA + *rB;
1977 STORE(EA, 2, *rS);
1978 *rA = EA;
1979 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RB_BITMASK | RS_BITMASK, 0);
1980
1981 0.36,6.RS,11.RA,16.D:D:::Store Word
1982 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1983 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1984 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1985 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1986 unsigned_word b;
1987 unsigned_word EA;
1988 if (RA == 0) b = 0;
1989 else b = *rA;
1990 EA = b + EXTS(D);
1991 STORE(EA, 4, *rS);
1992 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RS_BITMASK, 0);
1993
1994 0.31,6.RS,11.RA,16.RB,21.151,31./:X:::Store Word Indexed
1995 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1996 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1997 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1998 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1999 unsigned_word b;
2000 unsigned_word EA;
2001 if (RA == 0) b = 0;
2002 else b = *rA;
2003 EA = b + *rB;
2004 STORE(EA, 4, *rS);
2005 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
2006
2007 0.37,6.RS,11.RA,16.D:D:::Store Word with Update
2008 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2009 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2010 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2011 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2012 unsigned_word EA;
2013 if (RA == 0)
2014 program_interrupt(processor, cia,
2015 illegal_instruction_program_interrupt);
2016 EA = *rA + EXTS(D);
2017 STORE(EA, 4, *rS);
2018 *rA = EA;
2019 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RS_BITMASK, 0);
2020
2021 0.31,6.RS,11.RA,16.RB,21.183,31./:X:::Store Word with Update Indexed
2022 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2023 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2024 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2025 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2026 unsigned_word EA;
2027 if (RA == 0)
2028 program_interrupt(processor, cia,
2029 illegal_instruction_program_interrupt);
2030 EA = *rA + *rB;
2031 STORE(EA, 4, *rS);
2032 *rA = EA;
2033 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RB_BITMASK | RS_BITMASK, 0);
2034
2035 0.62,6.RS,11.RA,16.DS,30.0:DS:64::Store Doubleword
2036 # unsigned_word b;
2037 # unsigned_word EA;
2038 # if (RA == 0) b = 0;
2039 # else b = *rA;
2040 # EA = b + EXTS(DS_0b00);
2041 # STORE(EA, 8, *rS);
2042 0.31,6.RS,11.RA,16.RB,21.149,31./:X:64::Store Doubleword Indexed
2043 # unsigned_word b;
2044 # unsigned_word EA;
2045 # if (RA == 0) b = 0;
2046 # else b = *rA;
2047 # EA = b + *rB;
2048 # STORE(EA, 8, *rS);
2049 0.62,6.RS,11.RA,16.DS,30.1:DS:64::Store Doubleword with Update
2050 # unsigned_word EA;
2051 # if (RA == 0)
2052 # program_interrupt(processor, cia
2053 # illegal_instruction_program_interrupt);
2054 # EA = *rA + EXTS(DS_0b00);
2055 # STORE(EA, 8, *rS);
2056 # *rA = EA;
2057 0.31,6.RS,11.RA,16.RB,21.181,31./:X:64::Store Doubleword with Update Indexed
2058 # unsigned_word EA;
2059 # if (RA == 0)
2060 # program_interrupt(processor, cia
2061 # illegal_instruction_program_interrupt);
2062 # EA = *rA + *rB;
2063 # STORE(EA, 8, *rS);
2064 # *rA = EA;
2065
2066
2067 #
2068 # I.3.3.4 Fixed-Point Load and Store with Byte Reversal Instructions
2069 #
2070
2071 0.31,6.RT,11.RA,16.RB,21.790,31./:X:::Load Halfword Byte-Reverse Indexed
2072 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2073 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2074 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2075 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2076 unsigned_word b;
2077 unsigned_word EA;
2078 if (RA == 0) b = 0;
2079 else b = *rA;
2080 EA = b + *rB;
2081 *rT = SWAP_2(MEM(unsigned, EA, 2));
2082 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
2083
2084 0.31,6.RT,11.RA,16.RB,21.534,31./:X:::Load Word Byte-Reverse Indexed
2085 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2086 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2087 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2088 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2089 unsigned_word b;
2090 unsigned_word EA;
2091 if (RA == 0) b = 0;
2092 else b = *rA;
2093 EA = b + *rB;
2094 *rT = SWAP_4(MEM(unsigned, EA, 4));
2095 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
2096
2097 0.31,6.RS,11.RA,16.RB,21.918,31./:X:::Store Half Word Byte-Reversed Indexed
2098 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2099 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2100 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2101 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2102 unsigned_word b;
2103 unsigned_word EA;
2104 if (RA == 0) b = 0;
2105 else b = *rA;
2106 EA = b + *rB;
2107 STORE(EA, 2, SWAP_2(*rS));
2108 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
2109
2110 0.31,6.RS,11.RA,16.RB,21.662,31./:X:::Store Word Byte-Reversed Indexed
2111 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2112 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2113 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2114 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2115 unsigned_word b;
2116 unsigned_word EA;
2117 if (RA == 0) b = 0;
2118 else b = *rA;
2119 EA = b + *rB;
2120 STORE(EA, 4, SWAP_4(*rS));
2121 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
2122
2123
2124 #
2125 # I.3.3.5 Fixed-Point Load and Store Multiple Instrctions
2126 #
2127
2128 0.46,6.RT,11.RA,16.D:D:::Load Multiple Word
2129
2130 0.47,6.RS,11.RA,16.D:D:::Store Multiple Word
2131
2132
2133 #
2134 # I.3.3.6 Fixed-Point Move Assist Instructions
2135 #
2136
2137 0.31,6.RT,11.RA,16.NB,21.597,31./:X:::Load String Word Immediate
2138
2139 0.31,6.RT,11.RA,16.RB,21.533,31./:X:::Load String Word Indexed
2140
2141 0.31,6.RS,11.RA,16.NB,21.725,31./:X:::Store String Word Immedate
2142
2143 0.31,6.RS,11.RA,16.RB,21.661,31./:X:::Store String Word Indexed
2144
2145
2146 #
2147 # I.3.3.7 Storage Synchronization Instructions
2148 #
2149 # HACK: Rather than monitor addresses looking for a reason
2150 # to cancel a reservation. This code instead keeps
2151 # a copy of the data read from memory. Before performing
2152 # a store, the memory area is checked to see if it has
2153 # been changed.
2154 0.31,6.RT,11.RA,16.RB,21.20,31./:X:::Load Word And Reserve Indexed
2155 *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2156 *603: PPC_UNIT_LSU, PPC_UNIT_IU, 1, 2, 0
2157 *603e:PPC_UNIT_LSU, PPC_UNIT_IU, 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 == 0) b = 0;
2162 else b = *rA;
2163 EA = b + *rB;
2164 RESERVE = 1;
2165 RESERVE_ADDR = real_addr(EA, 1/*is-read?*/);
2166 RESERVE_DATA = MEM(unsigned, EA, 4);
2167 *rT = RESERVE_DATA;
2168 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
2169
2170 0.31,6.RT,11.RA,16.RB,21.84,31./:X:64::Load Doubleword And Reserve Indexed
2171 unsigned_word b;
2172 unsigned_word EA;
2173 if (RA == 0) b = 0;
2174 else b = *rA;
2175 EA = b + *rB;
2176 RESERVE = 1;
2177 RESERVE_ADDR = real_addr(EA, 1/*is-read?*/);
2178 RESERVE_DATA = MEM(unsigned, EA, 8);
2179 *rT = RESERVE_DATA;
2180 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
2181
2182 0.31,6.RS,11.RA,16.RB,21.150,31.1:X:::Store Word Conditional Indexed
2183 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2184 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 8, 8, 0
2185 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 8, 8, 0
2186 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 3, 0
2187 unsigned_word b;
2188 unsigned_word EA;
2189 if (RA == 0) b = 0;
2190 else b = *rA;
2191 EA = b + *rB;
2192 if (RESERVE) {
2193 if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/)
2194 && /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 4)) {
2195 STORE(EA, 4, *rS);
2196 CR_SET_XER_SO(0, cr_i_zero);
2197 }
2198 else {
2199 /* ment to randomly to store, we never do! */
2200 CR_SET_XER_SO(0, 0);
2201 }
2202 RESERVE = 0;
2203 }
2204 else {
2205 CR_SET_XER_SO(0, 0);
2206 }
2207 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 1/*Rc*/);
2208
2209 0.31,6.RS,11.RA,16.RB,21.214,31.1:X:64::Store Doubleword Conditional Indexed
2210 unsigned_word b;
2211 unsigned_word EA;
2212 if (RA == 0) b = 0;
2213 else b = *rA;
2214 EA = b + *rB;
2215 if (RESERVE) {
2216 if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/)
2217 && /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 8)) {
2218 STORE(EA, 8, *rS);
2219 CR_SET_XER_SO(0, cr_i_zero);
2220 }
2221 else {
2222 /* ment to randomly to store, we never do */
2223 CR_SET_XER_SO(0, 0);
2224 }
2225 RESERVE = 0;
2226 }
2227 else {
2228 CR_SET_XER_SO(0, 0);
2229 }
2230 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 1/*Rc*/);
2231
2232 0.31,6./,11./,16./,21.598,31./:X::sync:Synchronize
2233 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2234 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
2235 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
2236 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
2237 /* do nothing */
2238
2239
2240 #
2241 # I.3.3.9 Fixed-Point Arithmetic Instructions
2242 #
2243
2244 0.14,6.RT,11.RA,16.SI:D:::Add Immediate
2245 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2246 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2247 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2248 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2249 if (RA_is_0) *rT = EXTS(SI);
2250 else *rT = *rA + EXTS(SI);
2251 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rT, (long)*rT));
2252 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
2253
2254 0.15,6.RT,11.RA,16.SI:D:::Add Immediate Shifted
2255 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2256 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2257 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2258 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2259 if (RA_is_0) *rT = EXTS(SI) << 16;
2260 else *rT = *rA + (EXTS(SI) << 16);
2261 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rT, (long)*rT));
2262 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
2263
2264 0.31,6.RT,11.RA,16.RB,21.OE,22.266,31.Rc:XO:::Add
2265 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2266 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2267 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2268 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2269 ALU_BEGIN(*rA);
2270 ALU_ADD(*rB);
2271 ALU_END(*rT, 0/*CA*/, OE, Rc);
2272 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2273
2274 0.31,6.RT,11.RA,16.RB,21.OE,22.40,31.Rc:XO:::Subtract From
2275 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2276 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2277 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2278 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2279 ALU_BEGIN(*rA);
2280 ALU_NOT;
2281 ALU_ADD(*rB);
2282 ALU_ADD(1);
2283 ALU_END(*rT, 0/*CA*/, OE, Rc);
2284 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2285
2286 0.12,6.RT,11.RA,16.SI:D:::Add Immediate Carrying
2287 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2288 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2289 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2290 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2291 ALU_BEGIN(*rA);
2292 ALU_ADD(EXTS(SI));
2293 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
2294 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, 0/*Rc*/);
2295
2296 0.13,6.RT,11.RA,16.SI:D:::Add Immediate Carrying and Record
2297 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2298 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2299 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2300 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2301 ALU_BEGIN(*rA);
2302 ALU_ADD(EXTS(SI));
2303 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 1/*Rc*/);
2304 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, 1/*Rc*/);
2305
2306 0.8,6.RT,11.RA,16.SI:D:::Subtract From Immediate Carrying
2307 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2308 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2309 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2310 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2311 ALU_BEGIN(*rA);
2312 ALU_NOT;
2313 ALU_ADD(EXTS(SI));
2314 ALU_ADD(1);
2315 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
2316 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, 0/*Rc*/);
2317
2318 0.31,6.RT,11.RA,16.RB,21.OE,22.10,31.Rc:XO:::Add Carrying
2319 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2320 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2321 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2322 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2323 ALU_BEGIN(*rA);
2324 ALU_ADD(*rB);
2325 ALU_END(*rT, 1/*CA*/, OE, Rc);
2326 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2327
2328 0.31,6.RT,11.RA,16.RB,21.OE,22.8,31.Rc:XO:::Subtract From Carrying
2329 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2330 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2331 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2332 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2333 /* RT <- ~RA + RB + 1 === RT <- RB - RA */
2334 ALU_BEGIN(*rA);
2335 ALU_NOT;
2336 ALU_ADD(*rB);
2337 ALU_ADD(1);
2338 ALU_END(*rT, 1/*CA*/, OE, Rc);
2339 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2340
2341 0.31,6.RT,11.RA,16.RB,21.OE,22.138,31.Rc:XO:::Add Extended
2342 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2343 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2344 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2345 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2346 ALU_BEGIN(*rA);
2347 ALU_ADD(*rB);
2348 ALU_ADD_CA;
2349 ALU_END(*rT, 1/*CA*/, OE, Rc);
2350 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2351
2352 0.31,6.RT,11.RA,16.RB,21.OE,22.136,31.Rc:XO:::Subtract From Extended
2353 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2354 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2355 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2356 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2357 ALU_BEGIN(*rA);
2358 ALU_NOT;
2359 ALU_ADD(*rB);
2360 ALU_ADD_CA;
2361 ALU_END(*rT, 1/*CA*/, OE, Rc);
2362 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2363
2364 0.31,6.RT,11.RA,16./,21.OE,22.234,31.Rc:XO:::Add to Minus One Extended
2365 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2366 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2367 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2368 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2369 ALU_BEGIN(*rA);
2370 ALU_ADD_CA;
2371 ALU_ADD(-1);
2372 ALU_END(*rT, 1/*CA*/, OE, Rc);
2373 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2374
2375 0.31,6.RT,11.RA,16./,21.OE,22.232,31.Rc:XO:::Subtract From Minus One Extended
2376 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2377 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2378 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2379 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2380 ALU_BEGIN(*rA);
2381 ALU_NOT;
2382 ALU_ADD_CA;
2383 ALU_ADD(-1);
2384 ALU_END(*rT, 1/*CA*/, OE, Rc);
2385 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2386
2387 0.31,6.RT,11.RA,16./,21.OE,22.202,31.Rc:XO::addze:Add to Zero Extended
2388 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2389 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2390 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2391 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2392 ALU_BEGIN(*rA);
2393 ALU_ADD_CA;
2394 ALU_END(*rT, 1/*CA*/, OE, Rc);
2395 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2396
2397 0.31,6.RT,11.RA,16./,21.OE,22.200,31.Rc:XO:::Subtract from Zero Extended
2398 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2399 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2400 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2401 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2402 ALU_BEGIN(*rA);
2403 ALU_NOT;
2404 ALU_ADD_CA;
2405 ALU_END(*rT, 1/*CA*/, OE, Rc);
2406 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2407
2408 0.31,6.RT,11.RA,16./,21.OE,22.104,31.Rc:XO:::Negate
2409 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2410 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2411 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2412 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2413 ALU_BEGIN(*rA);
2414 ALU_NOT;
2415 ALU_ADD(1);
2416 ALU_END(*rT,0/*CA*/,OE,Rc);
2417 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2418
2419 0.7,6.RT,11.RA,16.SI:D::mulli:Multiply Low Immediate
2420 *601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2421 *603: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
2422 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
2423 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
2424 signed_word prod = *rA * EXTS(SI);
2425 *rT = prod;
2426 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, 0/*Rc*/);
2427
2428 0.31,6.RT,11.RA,16.RB,21.OE,22.233,31.Rc:D:64::Multiply Low Doubleword
2429
2430 0.31,6.RT,11.RA,16.RB,21.OE,22.235,31.Rc:XO::mullw:Multiply Low Word
2431 *601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2432 *603: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2433 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2434 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0
2435 signed64 a = (signed32)(*rA);
2436 signed64 b = (signed32)(*rB);
2437 signed64 prod = a * b;
2438 signed_word t = prod;
2439 *rT = *rA * *rB;
2440 if (t != prod && OE)
2441 XER |= (xer_overflow | xer_summary_overflow);
2442 CR0_COMPARE(t, 0, Rc);
2443 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2444
2445 0.31,6.RT,11.RA,16.RB,21./,22.73,31.Rc:XO:64::Multiply High Doubleword
2446
2447 0.31,6.RT,11.RA,16.RB,21./,22.75,31.Rc:XO::mulhw:Multiply High Word
2448 *601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2449 *603: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2450 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2451 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0
2452 signed64 a = (signed32)(*rA);
2453 signed64 b = (signed32)(*rB);
2454 signed64 prod = a * b;
2455 signed_word t = EXTRACTED64(prod, 0, 31);
2456 *rT = t;
2457 CR0_COMPARE(t, 0, Rc);
2458 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2459
2460 0.31,6.RT,11.RA,16.RB,21./,22.9,31.Rc:XO:64::Multiply High Doubleword Unsigned
2461
2462 0.31,6.RT,11.RA,16.RB,21./,22.11,31.Rc:XO::milhwu:Multiply High Word Unsigned
2463 *601: PPC_UNIT_IU, PPC_UNIT_IU, 10, 10, 0
2464 *603: PPC_UNIT_IU, PPC_UNIT_IU, 6, 6, 0
2465 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 6, 6, 0
2466 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0
2467 unsigned64 a = (unsigned32)(*rA);
2468 unsigned64 b = (unsigned32)(*rB);
2469 unsigned64 prod = a * b;
2470 signed_word t = EXTRACTED64(prod, 0, 31);
2471 *rT = t;
2472 CR0_COMPARE(t, 0, Rc);
2473 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2474
2475 0.31,6.RT,11.RA,16.RB,21.OE,22.489,31.Rc:XO:64::Divide Doubleword
2476
2477 0.31,6.RT,11.RA,16.RB,21.OE,22.491,31.Rc:XO::divw:Divide Word
2478 *601: PPC_UNIT_IU, PPC_UNIT_IU, 36, 36, 0
2479 *603: PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2480 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2481 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 20, 20, 0
2482 signed64 dividend = (signed32)(*rA);
2483 signed64 divisor = (signed32)(*rB);
2484 if (divisor == 0 /* nb 0x8000..0 is sign extended */
2485 || (dividend == 0x80000000 && divisor == -1)) {
2486 if (OE)
2487 XER |= (xer_overflow | xer_summary_overflow);
2488 CR0_COMPARE(0, 0, Rc);
2489 }
2490 else {
2491 signed64 quotent = dividend / divisor;
2492 *rT = quotent;
2493 CR0_COMPARE((signed_word)quotent, 0, Rc);
2494 }
2495 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2496
2497 0.31,6.RT,11.RA,16.RB,21.OE,22.457,31.Rc:XO:64::Divide Doubleword Unsigned
2498
2499 0.31,6.RT,11.RA,16.RB,21.OE,22.459,31.Rc:XO::divwu:Divide Word Unsigned
2500 *601: PPC_UNIT_IU, PPC_UNIT_IU, 36, 36, 0
2501 *603: PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2502 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2503 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 20, 20, 0
2504 unsigned64 dividend = (unsigned32)(*rA);
2505 unsigned64 divisor = (unsigned32)(*rB);
2506 if (divisor == 0) {
2507 if (OE)
2508 XER |= (xer_overflow | xer_summary_overflow);
2509 CR0_COMPARE(0, 0, Rc);
2510 }
2511 else {
2512 unsigned64 quotent = dividend / divisor;
2513 *rT = quotent;
2514 CR0_COMPARE((signed_word)quotent, 0, Rc);
2515 }
2516 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2517
2518
2519 #
2520 # I.3.3.10 Fixed-Point Compare Instructions
2521 #
2522
2523 0.11,6.BF,9./,10.L,11.RA,16.SI:D:::Compare Immediate
2524 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2525 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2526 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2527 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2528 if (!is_64bit_mode && L)
2529 program_interrupt(processor, cia,
2530 illegal_instruction_program_interrupt);
2531 else {
2532 signed_word a;
2533 signed_word b = EXTS(SI);
2534 if (L == 0)
2535 a = EXTENDED(*rA);
2536 else
2537 a = *rA;
2538 CR_COMPARE(BF, a, b);
2539 }
2540 PPC_INSN_INT_CR(0, RA_BITMASK, BF_BITMASK);
2541
2542 0.31,6.BF,9./,10.L,11.RA,16.RB,21.0,31./:X:::Compare
2543 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2544 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2545 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2546 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2547 if (!is_64bit_mode && L)
2548 program_interrupt(processor, cia,
2549 illegal_instruction_program_interrupt);
2550 else {
2551 signed_word a;
2552 signed_word b;
2553 if (L == 0) {
2554 a = EXTENDED(*rA);
2555 b = EXTENDED(*rB);
2556 }
2557 else {
2558 a = *rA;
2559 b = *rB;
2560 }
2561 CR_COMPARE(BF, a, b);
2562 }
2563 PPC_INSN_INT_CR(0, RA_BITMASK | RB_BITMASK, BF_BITMASK);
2564
2565 0.10,6.BF,9./,10.L,11.RA,16.UI:D:::Compare Logical Immediate
2566 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2567 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2568 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2569 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2570 if (!is_64bit_mode && L)
2571 program_interrupt(processor, cia,
2572 illegal_instruction_program_interrupt);
2573 else {
2574 unsigned_word a;
2575 unsigned_word b = UI;
2576 if (L == 0)
2577 a = MASKED(*rA, 32, 63);
2578 else
2579 a = *rA;
2580 CR_COMPARE(BF, a, b);
2581 }
2582 PPC_INSN_INT_CR(0, RA_BITMASK, BF_BITMASK);
2583
2584 0.31,6.BF,9./,10.L,11.RA,16.RB,21.32,31./:X:::Compare Logical
2585 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2586 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2587 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2588 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2589 if (!is_64bit_mode && L)
2590 program_interrupt(processor, cia,
2591 illegal_instruction_program_interrupt);
2592 else {
2593 unsigned_word a;
2594 unsigned_word b;
2595 if (L == 0) {
2596 a = MASKED(*rA, 32, 63);
2597 b = MASKED(*rB, 32, 63);
2598 }
2599 else {
2600 a = *rA;
2601 b = *rB;
2602 }
2603 CR_COMPARE(BF, a, b);
2604 }
2605 PPC_INSN_INT_CR(0, RA_BITMASK | RB_BITMASK, BF_BITMASK);
2606
2607
2608 #
2609 # I.3.3.11 Fixed-Point Trap Instructions
2610 #
2611
2612 0.2,6.TO,11.RA,16.SI:D:64::Trap Doubleword Immediate
2613 if (!is_64bit_mode)
2614 program_interrupt(processor, cia,
2615 illegal_instruction_program_interrupt);
2616 else {
2617 signed_word a = *rA;
2618 signed_word b = EXTS(SI);
2619 if ((a < b && TO{0})
2620 || (a > b && TO{1})
2621 || (a == b && TO{2})
2622 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2623 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2624 )
2625 program_interrupt(processor, cia,
2626 trap_program_interrupt);
2627 }
2628
2629 0.3,6.TO,11.RA,16.SI:D:::Trap Word Immediate
2630 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2631 *603: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2632 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2633 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2634 signed_word a = EXTENDED(*rA);
2635 signed_word b = EXTS(SI);
2636 if ((a < b && TO{0})
2637 || (a > b && TO{1})
2638 || (a == b && TO{2})
2639 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2640 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2641 )
2642 program_interrupt(processor, cia,
2643 trap_program_interrupt);
2644
2645 0.31,6.TO,11.RA,16.RB,21.68,31./:X:64::Trap Doubleword
2646 if (!is_64bit_mode)
2647 program_interrupt(processor, cia,
2648 illegal_instruction_program_interrupt);
2649 else {
2650 signed_word a = *rA;
2651 signed_word b = *rB;
2652 if ((a < b && TO{0})
2653 || (a > b && TO{1})
2654 || (a == b && TO{2})
2655 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2656 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2657 )
2658 program_interrupt(processor, cia,
2659 trap_program_interrupt);
2660 }
2661
2662 0.31,6.TO,11.RA,16.RB,21.4,31./:X:::Trap Word
2663 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2664 *603: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2665 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2666 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2667 signed_word a = EXTENDED(*rA);
2668 signed_word b = EXTENDED(*rB);
2669 if (TO == 12 && rA == rB) {
2670 ITRACE(trace_breakpoint, ("breakpoint\n"));
2671 cpu_halt(processor, cia, was_trap, 0);
2672 }
2673 else if ((a < b && TO{0})
2674 || (a > b && TO{1})
2675 || (a == b && TO{2})
2676 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2677 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2678 )
2679 program_interrupt(processor, cia,
2680 trap_program_interrupt);
2681
2682 #
2683 # I.3.3.12 Fixed-Point Logical Instructions
2684 #
2685
2686 0.28,6.RS,11.RA,16.UI:D:::AND Immediate
2687 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2688 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2689 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2690 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2691 *rA = *rS & UI;
2692 CR0_COMPARE(*rA, 0, 1/*Rc*/);
2693 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2694 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 1/*Rc*/);
2695
2696 0.29,6.RS,11.RA,16.UI:D:::AND Immediate Shifted
2697 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2698 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2699 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2700 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2701 *rA = *rS & (UI << 16);
2702 CR0_COMPARE(*rA, 0, 1/*Rc*/);
2703 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2704 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 1/*Rc*/);
2705
2706 0.24,6.RS,11.RA,16.UI:D:::OR Immediate
2707 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2708 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2709 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2710 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2711 *rA = *rS | UI;
2712 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2713 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 0/*Rc*/);
2714
2715 0.25,6.RS,11.RA,16.UI:D:::OR Immediate Shifted
2716 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2717 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2718 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2719 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2720 *rA = *rS | (UI << 16);
2721 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2722 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 0/*Rc*/);
2723
2724 0.26,6.RS,11.RA,16.UI:D:::XOR Immediate
2725 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2726 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2727 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2728 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2729 *rA = *rS ^ UI;
2730 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2731 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 0/*Rc*/);
2732
2733 0.27,6.RS,11.RA,16.UI:D:::XOR Immediate Shifted
2734 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2735 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2736 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2737 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2738 *rA = *rS ^ (UI << 16);
2739 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2740 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 0/*Rc*/);
2741
2742 0.31,6.RS,11.RA,16.RB,21.28,31.Rc:X:::AND
2743 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2744 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2745 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2746 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2747 *rA = *rS & *rB;
2748 CR0_COMPARE(*rA, 0, Rc);
2749 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2750 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2751
2752 0.31,6.RS,11.RA,16.RB,21.444,31.Rc:X:::OR
2753 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2754 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2755 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2756 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2757 *rA = *rS | *rB;
2758 CR0_COMPARE(*rA, 0, Rc);
2759 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2760 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2761
2762 0.31,6.RS,11.RA,16.RB,21.316,31.Rc:X:::XOR
2763 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2764 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2765 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2766 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2767 *rA = *rS ^ *rB;
2768 CR0_COMPARE(*rA, 0, Rc);
2769 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2770 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2771
2772 0.31,6.RS,11.RA,16.RB,21.476,31.Rc:X:::NAND
2773 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2774 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2775 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2776 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2777 *rA = ~(*rS & *rB);
2778 CR0_COMPARE(*rA, 0, Rc);
2779 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2780 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2781
2782 0.31,6.RS,11.RA,16.RB,21.124,31.Rc:X:::NOR
2783 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2784 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2785 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2786 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2787 *rA = ~(*rS | *rB);
2788 CR0_COMPARE(*rA, 0, Rc);
2789 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2790 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2791
2792 0.31,6.RS,11.RA,16.RB,21.284,31.Rc:X:::Equivalent
2793 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2794 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2795 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2796 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2797 *rA = ~(*rS ^ *rB); /* A === B */
2798 CR0_COMPARE(*rA, 0, Rc);
2799 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2800 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2801
2802 0.31,6.RS,11.RA,16.RB,21.60,31.Rc:X:::AND with Complement
2803 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2804 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2805 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2806 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2807 *rA = *rS & ~*rB;
2808 CR0_COMPARE(*rA, 0, Rc);
2809 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2810 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2811
2812 0.31,6.RS,11.RA,16.RB,21.412,31.Rc:X:::OR with Complement
2813 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2814 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2815 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2816 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2817 *rA = *rS | ~*rB;
2818 CR0_COMPARE(*rA, 0, Rc);
2819 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2820 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2821
2822 0.31,6.RS,11.RA,16./,21.954,31.Rc:X::extsb:Extend Sign Byte
2823 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2824 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2825 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2826 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2827 *rA = (signed_word)(signed8)*rS;
2828 CR0_COMPARE(*rA, 0, Rc);
2829 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2830 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
2831
2832 0.31,6.RS,11.RA,16./,21.922,31.Rc:X::extsh:Extend Sign Half Word
2833 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2834 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2835 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2836 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2837 *rA = (signed_word)(signed16)*rS;
2838 CR0_COMPARE(*rA, 0, Rc);
2839 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2840 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
2841
2842 0.31,6.RS,11.RA,16./,21.986,31.Rc:X:64::Extend Sign Word
2843 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2844 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2845 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2846 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2847 # *rA = (signed_word)(signed32)*rS;
2848 # CR0_COMPARE(*rA, 0, Rc);
2849
2850 0.31,6.RS,11.RA,16./,21.58,31.Rc:X:64::Count Leading Zeros Doubleword
2851 # int count = 0;
2852 # unsigned64 mask = BIT64(0);
2853 # unsigned64 source = *rS;
2854 # while (!(source & mask) && mask != 0) {
2855 # mask >>= 1;
2856 # count++;
2857 # }
2858 # *rA = count;
2859 # CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */
2860
2861 0.31,6.RS,11.RA,16./,21.26,31.Rc:X:::Count Leading Zeros Word
2862 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2863 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2864 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2865 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2866 int count = 0;
2867 unsigned32 mask = BIT32(0);
2868 unsigned32 source = *rS;
2869 while (!(source & mask) && mask != 0) {
2870 mask >>= 1;
2871 count++;
2872 }
2873 *rA = count;
2874 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2875 CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */
2876
2877
2878 #
2879 # I.3.3.13 Fixed-Point Rotate and Shift Instructions
2880 #
2881
2882 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
2883 # long n = (sh_5 << 4) | sh_0_4;
2884 # unsigned_word r = ROTL64(*rS, n);
2885 # long b = (mb_5 << 4) | mb_0_4;
2886 # unsigned_word m = MASK(b, 63);
2887 # signed_word result = r & m;
2888 # *rA = result;
2889 # ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2890 # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
2891
2892 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
2893 # long n = (sh_5 << 4) | sh_0_4;
2894 # unsigned_word r = ROTL64(*rS, n);
2895 # long e = (me_5 << 4) | me_0_4;
2896 # unsigned_word m = MASK(0, e);
2897 # signed_word result = r & m;
2898 # *rA = result;
2899 # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
2900
2901 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
2902 # long n = (sh_5 << 4) | sh_0_4;
2903 # unsigned_word r = ROTL64(*rS, n);
2904 # long b = (mb_5 << 4) | mb_0_4;
2905 # unsigned_word m = MASK(0, (64-n));
2906 # signed_word result = r & m;
2907 # *rA = result;
2908 # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
2909
2910 0.21,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M:::Rotate Left Word Immediate then AND with Mask
2911 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2912 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2913 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2914 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2915 long n = SH;
2916 unsigned32 s = *rS;
2917 unsigned32 r = ROTL32(s, n);
2918 unsigned32 m = MASK(MB+32, ME+32);
2919 signed_word result = r & m;
2920 *rA = result;
2921 CR0_COMPARE(result, 0, Rc);
2922 ITRACE(trace_alu,
2923 ("n=%ld, s=0x%lx, r=0x%lx, m=0x%lx, result=0x%lx, cr=0x%lx\n",
2924 n, (unsigned long)s, (unsigned long)r, (unsigned long)m,
2925 (unsigned long)result, (unsigned long)CR));
2926 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
2927
2928 0.30,6.RS,11.RA,16.RB,21.mb,27.8,31.Rc:MDS:64::Rotate Left Doubleword then Clear Left
2929 # long n = MASKED(*rB, 58, 63);
2930 # unsigned_word r = ROTL64(*rS, n);
2931 # long b = (mb_5 << 4) | mb_0_4;
2932 # unsigned_word m = MASK(b, 63);
2933 # signed_word result = r & m;
2934 # *rA = result;
2935 # CR0_COMPARE(result, 0, Rc);
2936
2937 0.30,6.RS,11.RA,16.RB,21.me,27.9,31.Rc:MDS:64::Rotate Left Doubleword then Clear Right
2938 # long n = MASKED(*rB, 58, 63);
2939 # unsigned_word r = ROTL64(*rS, n);
2940 # long e = (me_5 << 4) | me_0_4;
2941 # unsigned_word m = MASK(0, e);
2942 # signed_word result = r & m;
2943 # *rA = result;
2944 # CR0_COMPARE(result, 0, Rc);
2945
2946 0.23,6.RS,11.RA,16.RB,21.MB,26.ME,31.Rc:M:::Rotate Left Word then AND with Mask
2947 # long n = MASKED(*rB, 59, 63);
2948 # unsigned32 r = ROTL32(*rS, n);
2949 # unsigned32 m = MASK(MB+32, ME+32);
2950 # signed_word result = r & m;
2951 # *rA = result;
2952 # CR0_COMPARE(result, 0, Rc);
2953
2954 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
2955 # long n = (sh_5 << 4) | sh_0_4;
2956 # unsigned_word r = ROTL64(*rS, n);
2957 # long b = (mb_5 << 4) | mb_0_4;
2958 # unsigned_word m = MASK(b, (64-n));
2959 # signed_word result = (r & m) | (*rA & ~m)
2960 # *rA = result;
2961 # CR0_COMPARE(result, 0, Rc);
2962
2963 0.20,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M::rlwimi:Rotate Left Word Immediate then Mask Insert
2964 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2965 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2966 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2967 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2968 long n = SH;
2969 unsigned32 r = ROTL32(*rS, n);
2970 unsigned32 m = MASK(MB+32, ME+32);
2971 signed_word result = (r & m) | (*rA & ~m);
2972 *rA = result;
2973 ITRACE(trace_alu, (": n=%ld *rS=0x%lx r=0x%lx m=0x%lx result=0x%lx\n",
2974 n, (unsigned long)*rS, (unsigned long)r, (unsigned long)m,
2975 (unsigned long)result));
2976 CR0_COMPARE(result, 0, Rc);
2977 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
2978
2979
2980 0.31,6.RS,11.RA,16.RB,21.27,31.Rc:X:64::Shift Left Doubleword
2981
2982 0.31,6.RS,11.RA,16.RB,21.24,31.Rc:X:::Shift Left Word
2983 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2984 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2985 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2986 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2987 int n = MASKED(*rB, 59, 63);
2988 unsigned32 source = *rS;
2989 signed_word shifted;
2990 if (n < 32)
2991 shifted = (source << n);
2992 else
2993 shifted = 0;
2994 *rA = shifted;
2995 CR0_COMPARE(shifted, 0, Rc);
2996 ITRACE(trace_alu,
2997 ("n=%d, source=0x%lx, shifted=0x%lx\n",
2998 n, (unsigned long)source, (unsigned long)shifted));
2999 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3000
3001 0.31,6.RS,11.RA,16.RB,21.539,31.Rc:X:64::Shift Right Doubleword
3002
3003 0.31,6.RS,11.RA,16.RB,21.536,31.Rc:X:::Shift Right Word
3004 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3005 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3006 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3007 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3008 int n = MASKED(*rB, 59, 63);
3009 unsigned32 source = *rS;
3010 signed_word shifted;
3011 if (n < 32)
3012 shifted = (source >> n);
3013 else
3014 shifted = 0;
3015 *rA = shifted;
3016 CR0_COMPARE(shifted, 0, Rc);
3017 ITRACE(trace_alu, \
3018 ("n=%d, source=0x%lx, shifted=0x%lx\n",
3019 n, (unsigned long)source, (unsigned long)shifted));
3020 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3021
3022 0.31,6.RS,11.RA,16.sh_0_4,21.413,30.sh_5,31.Rc:XS:64::Shift Right Algebraic Doubleword Immediate
3023
3024 0.31,6.RS,11.RA,16.SH,21.824,31.Rc:X:::Shift Right Algebraic Word Immediate
3025 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3026 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3027 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3028 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3029 int n = SH;
3030 signed_word r = ROTL32(*rS, /*64*/32-n);
3031 signed_word m = MASK(n+32, 63);
3032 int S = MASKED(*rS, 32, 32);
3033 signed_word shifted = (r & m) | (S ? ~m : 0);
3034 *rA = shifted;
3035 if (S && ((r & ~m) & MASK(32, 63)) != 0)
3036 XER |= xer_carry;
3037 else
3038 XER &= ~xer_carry;
3039 CR0_COMPARE(shifted, 0, Rc);
3040 ITRACE(trace_alu, (" Result = %ld (0x%lx), XER = %ld\n",
3041 (long)*rA, (long)*rA, (long)XER));
3042 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3043
3044 0.31,6.RS,11.RA,16.RB,21.794,31.Rc:X:64::Shift Right Algebraic Doubleword
3045
3046 0.31,6.RS,11.RA,16.RB,21.792,31.Rc:X:::Shift Right Algebraic Word
3047 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3048 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3049 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3050 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3051 int n = MASKED(*rB, 58, 63);
3052 int shift = (n >= 31 ? 31 : n);
3053 signed32 source = (signed32)*rS; /* signed to keep sign bit */
3054 signed32 shifted = source >> shift;
3055 unsigned32 mask = ((unsigned32)-1) >> (31-shift);
3056 *rA = (signed_word)shifted; /* if 64bit will sign extend */
3057 if (source < 0 && (source & mask))
3058 XER |= xer_carry;
3059 else
3060 XER &= ~xer_carry;
3061 CR0_COMPARE(shifted, 0, Rc);
3062 ITRACE(trace_alu, (" Result = %ld (0x%lx), XER = %ld\n",
3063 (long)*rA, (long)*rA, (long)XER));
3064 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3065
3066 #
3067 # I.3.3.14 Move to/from System Register Instructions
3068 #
3069
3070 0.31,6.RS,11.SPR,21.467,31./:XFX::mtspr %SPR, %RS:Move to Special Purpose Register
3071 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3072 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
3073 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
3074 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
3075 int n = (SPR{5:9} << 5) | SPR{0:4};
3076 if (SPR{0} && IS_PROBLEM_STATE(processor))
3077 program_interrupt(processor, cia,
3078 privileged_instruction_program_interrupt);
3079 else if (!spr_is_valid(n)
3080 || spr_is_readonly(n))
3081 program_interrupt(processor, cia,
3082 illegal_instruction_program_interrupt);
3083 else {
3084 spreg new_val = (spr_length(n) == 64
3085 ? *rS
3086 : MASKED(*rS, 32, 63));
3087 /* HACK - time base registers need to be updated immediatly */
3088 if (WITH_TIME_BASE) {
3089 switch (n) {
3090 case spr_tbu:
3091 cpu_set_time_base(processor,
3092 (MASKED64(cpu_get_time_base(processor), 32, 63)
3093 | INSERTED64(new_val, 0, 31)));
3094 break;
3095 case spr_tbl:
3096 cpu_set_time_base(processor,
3097 (MASKED64(cpu_get_time_base(processor), 0, 31)
3098 | INSERTED64(new_val, 32, 63)));
3099 break;
3100 case spr_dec:
3101 cpu_set_decrementer(processor, new_val);
3102 break;
3103 default:
3104 SPREG(n) = new_val;
3105 break;
3106 }
3107 }
3108 else {
3109 SPREG(n) = new_val;
3110 }
3111 }
3112 PPC_INSN_TO_SPR(RS_BITMASK, n);
3113
3114 0.31,6.RT,11.SPR,21.339,31./:XFX::mfspr %RT, %SPR:Move from Special Purpose Register
3115 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3116 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3117 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3118 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
3119 int n = (SPR{5:9} << 5) | SPR{0:4};
3120 if (SPR{0} && IS_PROBLEM_STATE(processor))
3121 program_interrupt(processor, cia,
3122 privileged_instruction_program_interrupt);
3123 else if (!spr_is_valid(n))
3124 program_interrupt(processor, cia,
3125 illegal_instruction_program_interrupt);
3126 else {
3127 /* HACK - some SPR's need to get their value extracted specially */
3128 *rT = SPREG(n);
3129 }
3130 PPC_INSN_FROM_SPR(RT_BITMASK, n);
3131
3132 0.31,6.RS,11./,12.FXM,20./,21.144,31./:XFX::mtfcr:Move to Condition Register Fields
3133 *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
3134 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3135 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3136 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
3137 if (FXM == 0xff) {
3138 CR = *rS;
3139 }
3140 else {
3141 unsigned_word mask = 0;
3142 unsigned_word f;
3143 for (f = 0; f < 8; f++) {
3144 if (FXM & (0x80 >> f))
3145 mask |= (0xf << 4*(7-f));
3146 }
3147 CR = (MASKED(*rS, 32, 63) & mask) | (CR & ~mask);
3148 }
3149 PPC_INSN_MTCR(RS_BITMASK, FXM);
3150
3151 0.31,6.BF,9./,11./,16./,21.512,31./:X:::Move to Condition Register from XER
3152
3153 0.31,6.RT,11./,16./,21.19,31./:X:::Move From Condition Register
3154 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3155 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3156 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3157 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
3158 *rT = (unsigned32)CR;
3159 PPC_INSN_MFCR(RT_BITMASK);
3160
3161 #
3162 # I.4.6.2 Floating-Point Load Instructions
3163 #
3164
3165 0.48,6.FRT,11.RA,16.D:D:f:lfs:Load Floating-Point Single
3166 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3167 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3168 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3169 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3170 unsigned_word b;
3171 unsigned_word EA;
3172 if (RA == 0) b = 0;
3173 else b = *rA;
3174 EA = b + EXTS(D);
3175 *frT = DOUBLE(MEM(unsigned, EA, 4));
3176 PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3177
3178 0.31,6.FRT,11.RA,16.RB,21.535,31./:X:f::Load Floating-Point Single Indexed
3179 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3180 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3181 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3182 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3183 unsigned_word b;
3184 unsigned_word EA;
3185 if (RA == 0) b = 0;
3186 else b = *rA;
3187 EA = b + *rB;
3188 *frT = DOUBLE(MEM(unsigned, EA, 4));
3189 PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3190
3191 0.49,6.FRT,11.RA,16.D:D:f::Load Floating-Point Single with Update
3192 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3193 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3194 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3195 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3196 unsigned_word EA;
3197 if (RA == 0)
3198 program_interrupt(processor, cia,
3199 illegal_instruction_program_interrupt);
3200 EA = *rA + EXTS(D);
3201 *frT = DOUBLE(MEM(unsigned, EA, 4));
3202 *rA = EA;
3203 PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3204
3205 0.31,6.FRT,11.RA,16.RB,21.576,31./:X:f::Load Floating-Point Single with Update Indexed
3206 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3207 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3208 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3209 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3210 unsigned_word EA;
3211 if (RA == 0)
3212 program_interrupt(processor, cia,
3213 illegal_instruction_program_interrupt);
3214 EA = *rA + *rB;
3215 *frT = DOUBLE(MEM(unsigned, EA, 4));
3216 *rA = EA;
3217 PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3218
3219 0.50,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double
3220 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3221 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3222 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3223 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3224 unsigned_word b;
3225 unsigned_word EA;
3226 if (RA == 0) b = 0;
3227 else b = *rA;
3228 EA = b + EXTS(D);
3229 *frT = MEM(unsigned, EA, 8);
3230 PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3231
3232 0.31,6.FRT,11.RA,16.RB,21.599,31./:X:f::Load Floating-Point Double Indexed
3233 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3234 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3235 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3236 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3237 unsigned_word b;
3238 unsigned_word EA;
3239 if (RA == 0) b = 0;
3240 else b = *rA;
3241 EA = b + *rB;
3242 *frT = MEM(unsigned, EA, 8);
3243 PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3244
3245 0.51,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double with Update
3246 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3247 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3248 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3249 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3250 unsigned_word EA;
3251 if (RA == 0)
3252 program_interrupt(processor, cia,
3253 illegal_instruction_program_interrupt);
3254 EA = *rA + EXTS(D);
3255 *frT = MEM(unsigned, EA, 8);
3256 *rA = EA;
3257 PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3258
3259 0.31,6.FRT,11.RA,16.RB,21.631,31./:X:f::Load Floating-Point Double with Update Indexed
3260 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3261 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3262 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3263 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3264 unsigned_word EA;
3265 if (RA == 0)
3266 program_interrupt(processor, cia,
3267 illegal_instruction_program_interrupt);
3268 EA = *rA + *rB;
3269 *frT = MEM(unsigned, EA, 8);
3270 *rA = EA;
3271 PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3272
3273
3274 #
3275 # I.4.6.3 Floating-Point Store Instructions
3276 #
3277
3278 0.52,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single
3279 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3280 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3281 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3282 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3283 unsigned_word b;
3284 unsigned_word EA;
3285 if (RA == 0) b = 0;
3286 else b = *rA;
3287 EA = b + EXTS(D);
3288 STORE(EA, 4, SINGLE(*frS));
3289 PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3290
3291 0.31,6.FRS,11.RA,16.RB,21.663,31./:X:f::Store Floating-Point Single Indexed
3292 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3293 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3294 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3295 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3296 unsigned_word b;
3297 unsigned_word EA;
3298 if (RA == 0) b = 0;
3299 else b = *rA;
3300 EA = b + *rB;
3301 STORE(EA, 4, SINGLE(*frS));
3302 PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3303
3304 0.53,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single with Update
3305 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3306 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3307 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3308 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3309 unsigned_word EA;
3310 if (RA == 0)
3311 program_interrupt(processor, cia,
3312 illegal_instruction_program_interrupt);
3313 EA = *rA + EXTS(D);
3314 STORE(EA, 4, SINGLE(*frS));
3315 *rA = EA;
3316 PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3317
3318 0.31,6.FRS,11.RA,16.RB,21.695,31./:X:f::Store Floating-Point Single with Update Indexed
3319 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3320 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3321 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3322 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3323 unsigned_word EA;
3324 if (RA == 0)
3325 program_interrupt(processor, cia,
3326 illegal_instruction_program_interrupt);
3327 EA = *rA + *rB;
3328 STORE(EA, 4, SINGLE(*frS));
3329 *rA = EA;
3330 PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3331
3332 0.54,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double
3333 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3334 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3335 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3336 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3337 unsigned_word b;
3338 unsigned_word EA;
3339 if (RA == 0) b = 0;
3340 else b = *rA;
3341 EA = b + EXTS(D);
3342 STORE(EA, 8, *frS);
3343 PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3344
3345 0.31,6.FRS,11.RA,16.RB,21.727,31./:X:f::Store Floating-Point Double Indexed
3346 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3347 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3348 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3349 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3350 unsigned_word b;
3351 unsigned_word EA;
3352 if (RA == 0) b = 0;
3353 else b = *rA;
3354 EA = b + *rB;
3355 STORE(EA, 8, *frS);
3356 PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3357
3358 0.55,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double with Update
3359 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3360 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3361 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3362 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3363 unsigned_word EA;
3364 if (RA == 0)
3365 program_interrupt(processor, cia,
3366 illegal_instruction_program_interrupt);
3367 EA = *rA + EXTS(D);
3368 STORE(EA, 8, *frS);
3369 *rA = EA;
3370 PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3371
3372 0.31,6.FRS,11.RA,16.RB,21.759,31./:X:f::Store Floating-Point Double with Update Indexed
3373 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3374 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3375 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3376 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3377 unsigned_word EA;
3378 if (RA == 0)
3379 program_interrupt(processor, cia,
3380 illegal_instruction_program_interrupt);
3381 EA = *rA + *rB;
3382 STORE(EA, 8, *frS);
3383 *rA = EA;
3384 PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3385
3386
3387 #
3388 # I.4.6.4 Floating-Point Move Instructions
3389 #
3390
3391 0.63,6.FRT,11./,16.FRB,21.72,31.Rc:X:f::Floating Move Register
3392 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3393 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3394 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3395 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3396 *frT = *frB;
3397 CR1_UPDATE(Rc);
3398 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3399
3400 0.63,6.FRT,11./,16.FRB,21.40,31.Rc:X:f::Floating Negate
3401 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3402 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3403 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3404 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3405 *frT = *frB ^ BIT64(0);
3406 CR1_UPDATE(Rc);
3407 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3408
3409 0.63,6.FRT,11./,16.FRB,21.264,31.Rc:X:f::Floating Absolute Value
3410 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3411 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3412 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3413 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3414 *frT = *frB & ~BIT64(0);
3415 CR1_UPDATE(Rc);
3416 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3417
3418 0.63,6.FRT,11./,16.FRB,21.136,31.Rc:X:f::Floating Negative Absolute Value
3419 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3420 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3421 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3422 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3423 *frT = *frB | BIT64(0);
3424 CR1_UPDATE(Rc);
3425 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3426
3427
3428 #
3429 # I.4.6.5 Floating-Point Arithmetic Instructions
3430 #
3431
3432 0.63,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadd:Floating Add
3433 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3434 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3435 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3436 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3437 FPSCR_BEGIN;
3438 if (is_invalid_operation(processor, cia,
3439 *frA, *frB,
3440 fpscr_vxsnan | fpscr_vxisi,
3441 0, /*single?*/
3442 0) /*negate?*/) {
3443 invalid_arithemetic_operation(processor, cia,
3444 frT, *frA, *frB, 0,
3445 0, /*instruction_is_frsp*/
3446 0, /*instruction_is_convert_to_64bit*/
3447 0, /*instruction_is_convert_to_32bit*/
3448 0); /*single-precision*/
3449 }
3450 else {
3451 /*HACK!*/
3452 double s = *(double*)frA + *(double*)frB;
3453 *(double*)frT = s;
3454 }
3455 FPSCR_END(Rc);
3456 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3457
3458 0.59,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadds:Floating Add Single
3459 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3460 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3461 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3462 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3463 FPSCR_BEGIN;
3464 if (is_invalid_operation(processor, cia,
3465 *frA, *frB,
3466 fpscr_vxsnan | fpscr_vxisi,
3467 1, /*single?*/
3468 0) /*negate?*/) {
3469 invalid_arithemetic_operation(processor, cia,
3470 frT, *frA, *frB, 0,
3471 0, /*instruction_is_frsp*/
3472 0, /*instruction_is_convert_to_64bit*/
3473 0, /*instruction_is_convert_to_32bit*/
3474 1); /*single-precision*/
3475 }
3476 else {
3477 /*HACK!*/
3478 float s = *(double*)frA + *(double*)frB;
3479 *(double*)frT = s;
3480 }
3481 FPSCR_END(Rc);
3482 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3483
3484 0.63,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsub:Floating Subtract
3485 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3486 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3487 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3488 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3489 FPSCR_BEGIN;
3490 if (is_invalid_operation(processor, cia,
3491 *frA, *frB,
3492 fpscr_vxsnan | fpscr_vxisi,
3493 0, /*single?*/
3494 1) /*negate?*/) {
3495 invalid_arithemetic_operation(processor, cia,
3496 frT, *frA, *frB, 0,
3497 0, /*instruction_is_frsp*/
3498 0, /*instruction_is_convert_to_64bit*/
3499 0, /*instruction_is_convert_to_32bit*/
3500 0); /*single-precision*/
3501 }
3502 else {
3503 /*HACK!*/
3504 double s = *(double*)frA - *(double*)frB;
3505 *(double*)frT = s;
3506 }
3507 FPSCR_END(Rc);
3508 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3509
3510 0.59,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsubs:Floating Subtract Single
3511 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3512 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3513 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3514 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3515 FPSCR_BEGIN;
3516 if (is_invalid_operation(processor, cia,
3517 *frA, *frB,
3518 fpscr_vxsnan | fpscr_vxisi,
3519 1, /*single?*/
3520 1) /*negate?*/) {
3521 invalid_arithemetic_operation(processor, cia,
3522 frT, *frA, *frB, 0,
3523 0, /*instruction_is_frsp*/
3524 0, /*instruction_is_convert_to_64bit*/
3525 0, /*instruction_is_convert_to_32bit*/
3526 1); /*single-precision*/
3527 }
3528 else {
3529 /*HACK!*/
3530 float s = *(double*)frA - *(double*)frB;
3531 *(double*)frT = s;
3532 }
3533 FPSCR_END(Rc);
3534 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3535
3536 0.63,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmul:Floating Multiply
3537 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3538 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3539 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3540 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3541 FPSCR_BEGIN;
3542 if (is_invalid_operation(processor, cia,
3543 *frA, *frC,
3544 fpscr_vxsnan | fpscr_vximz,
3545 0, /*single?*/
3546 0) /*negate?*/) {
3547 invalid_arithemetic_operation(processor, cia,
3548 frT, *frA, 0, *frC,
3549 0, /*instruction_is_frsp*/
3550 0, /*instruction_is_convert_to_64bit*/
3551 0, /*instruction_is_convert_to_32bit*/
3552 0); /*single-precision*/
3553 }
3554 else {
3555 /*HACK!*/
3556 double s = *(double*)frA * *(double*)frC;
3557 *(double*)frT = s;
3558 }
3559 FPSCR_END(Rc);
3560 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRC_BITMASK, Rc);
3561
3562 0.59,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmuls:Floating Multiply Single
3563 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3564 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3565 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3566 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3567 FPSCR_BEGIN;
3568 if (is_invalid_operation(processor, cia,
3569 *frA, *frC,
3570 fpscr_vxsnan | fpscr_vximz,
3571 1, /*single?*/
3572 0) /*negate?*/) {
3573 invalid_arithemetic_operation(processor, cia,
3574 frT, *frA, 0, *frC,
3575 0, /*instruction_is_frsp*/
3576 0, /*instruction_is_convert_to_64bit*/
3577 0, /*instruction_is_convert_to_32bit*/
3578 1); /*single-precision*/
3579 }
3580 else {
3581 /*HACK!*/
3582 float s = *(double*)frA * *(double*)frC;
3583 *(double*)frT = s;
3584 }
3585 FPSCR_END(Rc);
3586 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRC_BITMASK, Rc);
3587
3588 0.63,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdiv:Floating Divide
3589 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 31, 31, 0
3590 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 33, 33, 0
3591 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 33, 33, 0
3592 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 32, 32, 0
3593 FPSCR_BEGIN;
3594 if (is_invalid_operation(processor, cia,
3595 *frA, *frB,
3596 fpscr_vxsnan | fpscr_vxzdz,
3597 0, /*single?*/
3598 0) /*negate?*/) {
3599 invalid_arithemetic_operation(processor, cia,
3600 frT, *frA, *frB, 0,
3601 0, /*instruction_is_frsp*/
3602 0, /*instruction_is_convert_to_64bit*/
3603 0, /*instruction_is_convert_to_32bit*/
3604 0); /*single-precision*/
3605 }
3606 else {
3607 /*HACK!*/
3608 double s = *(double*)frA / *(double*)frB;
3609 *(double*)frT = s;
3610 }
3611 FPSCR_END(Rc);
3612 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3613
3614 0.59,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdivs:Floating Divide Single
3615 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 17, 17, 0
3616 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0
3617 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0
3618 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0
3619 FPSCR_BEGIN;
3620 if (is_invalid_operation(processor, cia,
3621 *frA, *frB,
3622 fpscr_vxsnan | fpscr_vxzdz,
3623 1, /*single?*/
3624 0) /*negate?*/) {
3625 invalid_arithemetic_operation(processor, cia,
3626 frT, *frA, *frB, 0,
3627 0, /*instruction_is_frsp*/
3628 0, /*instruction_is_convert_to_64bit*/
3629 0, /*instruction_is_convert_to_32bit*/
3630 1); /*single-precision*/
3631 }
3632 else {
3633 /*HACK!*/
3634 float s = *(double*)frA / *(double*)frB;
3635 *(double*)frT = s;
3636 }
3637 FPSCR_END(Rc);
3638 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3639
3640 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f:fmadd:Floating Multiply-Add
3641 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3642 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3643 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3644 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3645 FPSCR_BEGIN;
3646 double product; /*HACK! - incorrectly loosing precision ... */
3647 /* compute the multiply */
3648 if (is_invalid_operation(processor, cia,
3649 *frA, *frC,
3650 fpscr_vxsnan | fpscr_vximz,
3651 0, /*single?*/
3652 0) /*negate?*/) {
3653 invalid_arithemetic_operation(processor, cia,
3654 (unsigned64*)&product, *frA, 0, *frC,
3655 0, /*instruction_is_frsp*/
3656 0, /*instruction_is_convert_to_64bit*/
3657 0, /*instruction_is_convert_to_32bit*/
3658 0); /*single-precision*/
3659 }
3660 else {
3661 /*HACK!*/
3662 product = *(double*)frA * *(double*)frC;
3663 }
3664 /* compute the add */
3665 if (is_invalid_operation(processor, cia,
3666 product, *frB,
3667 fpscr_vxsnan | fpscr_vxisi,
3668 0, /*single?*/
3669 0) /*negate?*/) {
3670 invalid_arithemetic_operation(processor, cia,
3671 frT, product, *frB, 0,
3672 0, /*instruction_is_frsp*/
3673 0, /*instruction_is_convert_to_64bit*/
3674 0, /*instruction_is_convert_to_32bit*/
3675 0); /*single-precision*/
3676 }
3677 else {
3678 /*HACK!*/
3679 double s = product + *(double*)frB;
3680 *(double*)frT = s;
3681 }
3682 FPSCR_END(Rc);
3683 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
3684
3685 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f::Floating Multiply-Add Single
3686 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3687 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3688 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3689 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3690 FPSCR_BEGIN;
3691 float product; /*HACK! - incorrectly loosing precision ... */
3692 /* compute the multiply */
3693 if (is_invalid_operation(processor, cia,
3694 *frA, *frC,
3695 fpscr_vxsnan | fpscr_vximz,
3696 1, /*single?*/
3697 0) /*negate?*/) {
3698 invalid_arithemetic_operation(processor, cia,
3699 (unsigned64*)&product, *frA, 0, *frC,
3700 0, /*instruction_is_frsp*/
3701 0, /*instruction_is_convert_to_64bit*/
3702 0, /*instruction_is_convert_to_32bit*/
3703 0); /*single-precision*/
3704 }
3705 else {
3706 /*HACK!*/
3707 product = *(double*)frA * *(double*)frC;
3708 }
3709 /* compute the add */
3710 if (is_invalid_operation(processor, cia,
3711 product, *frB,
3712 fpscr_vxsnan | fpscr_vxisi,
3713 1, /*single?*/
3714 0) /*negate?*/) {
3715 invalid_arithemetic_operation(processor, cia,
3716 frT, product, *frB, 0,
3717 0, /*instruction_is_frsp*/
3718 0, /*instruction_is_convert_to_64bit*/
3719 0, /*instruction_is_convert_to_32bit*/
3720 0); /*single-precision*/
3721 }
3722 else {
3723 /*HACK!*/
3724 float s = product + *(double*)frB;
3725 *(double*)frT = (double)s;
3726 }
3727 FPSCR_END(Rc);
3728 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
3729
3730 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract
3731 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3732 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3733 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3734 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3735 FPSCR_BEGIN;
3736 double product; /*HACK! - incorrectly loosing precision ... */
3737 /* compute the multiply */
3738 if (is_invalid_operation(processor, cia,
3739 *frA, *frC,
3740 fpscr_vxsnan | fpscr_vximz,
3741 0, /*single?*/
3742 0) /*negate?*/) {
3743 invalid_arithemetic_operation(processor, cia,
3744 (unsigned64*)&product, *frA, 0, *frC,
3745 0, /*instruction_is_frsp*/
3746 0, /*instruction_is_convert_to_64bit*/
3747 0, /*instruction_is_convert_to_32bit*/
3748 0); /*single-precision*/
3749 }
3750 else {
3751 /*HACK!*/
3752 product = *(double*)frA * *(double*)frC;
3753 }
3754 /* compute the subtract */
3755 if (is_invalid_operation(processor, cia,
3756 product, *frB,
3757 fpscr_vxsnan | fpscr_vxisi,
3758 0, /*single?*/
3759 0) /*negate?*/) {
3760 invalid_arithemetic_operation(processor, cia,
3761 frT, product, *frB, 0,
3762 0, /*instruction_is_frsp*/
3763 0, /*instruction_is_convert_to_64bit*/
3764 0, /*instruction_is_convert_to_32bit*/
3765 0); /*single-precision*/
3766 }
3767 else {
3768 /*HACK!*/
3769 double s = product - *(double*)frB;
3770 *(double*)frT = s;
3771 }
3772 FPSCR_END(Rc);
3773 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
3774
3775 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract Single
3776 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3777 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3778 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3779 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3780 FPSCR_BEGIN;
3781 float product; /*HACK! - incorrectly loosing precision ... */
3782 /* compute the multiply */
3783 if (is_invalid_operation(processor, cia,
3784 *frA, *frC,
3785 fpscr_vxsnan | fpscr_vximz,
3786 1, /*single?*/
3787 0) /*negate?*/) {
3788 invalid_arithemetic_operation(processor, cia,
3789 (unsigned64*)&product, *frA, 0, *frC,
3790 0, /*instruction_is_frsp*/
3791 0, /*instruction_is_convert_to_64bit*/
3792 0, /*instruction_is_convert_to_32bit*/
3793 0); /*single-precision*/
3794 }
3795 else {
3796 /*HACK!*/
3797 product = *(double*)frA * *(double*)frC;
3798 }
3799 /* compute the subtract */
3800 if (is_invalid_operation(processor, cia,
3801 product, *frB,
3802 fpscr_vxsnan | fpscr_vxisi,
3803 1, /*single?*/
3804 0) /*negate?*/) {
3805 invalid_arithemetic_operation(processor, cia,
3806 frT, product, *frB, 0,
3807 0, /*instruction_is_frsp*/
3808 0, /*instruction_is_convert_to_64bit*/
3809 0, /*instruction_is_convert_to_32bit*/
3810 0); /*single-precision*/
3811 }
3812 else {
3813 /*HACK!*/
3814 float s = product - *(double*)frB;
3815 *(double*)frT = (double)s;
3816 }
3817 FPSCR_END(Rc);
3818 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
3819
3820 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add
3821 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3822 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3823 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3824 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3825 FPSCR_BEGIN;
3826 double product; /*HACK! - incorrectly loosing precision ... */
3827 /* compute the multiply */
3828 if (is_invalid_operation(processor, cia,
3829 *frA, *frC,
3830 fpscr_vxsnan | fpscr_vximz,
3831 0, /*single?*/
3832 0) /*negate?*/) {
3833 invalid_arithemetic_operation(processor, cia,
3834 (unsigned64*)&product, *frA, 0, *frC,
3835 0, /*instruction_is_frsp*/
3836 0, /*instruction_is_convert_to_64bit*/
3837 0, /*instruction_is_convert_to_32bit*/
3838 0); /*single-precision*/
3839 }
3840 else {
3841 /*HACK!*/
3842 product = *(double*)frA * *(double*)frC;
3843 }
3844 /* compute the add */
3845 if (is_invalid_operation(processor, cia,
3846 product, *frB,
3847 fpscr_vxsnan | fpscr_vxisi,
3848 0, /*single?*/
3849 0) /*negate?*/) {
3850 invalid_arithemetic_operation(processor, cia,
3851 frT, product, *frB, 0,
3852 0, /*instruction_is_frsp*/
3853 0, /*instruction_is_convert_to_64bit*/
3854 0, /*instruction_is_convert_to_32bit*/
3855 0); /*single-precision*/
3856 }
3857 else {
3858 /*HACK!*/
3859 double s = -(product + *(double*)frB);
3860 *(double*)frT = s;
3861 }
3862 FPSCR_END(Rc);
3863 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
3864
3865 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add Single
3866 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3867 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3868 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3869 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3870 FPSCR_BEGIN;
3871 float product; /*HACK! - incorrectly loosing precision ... */
3872 /* compute the multiply */
3873 if (is_invalid_operation(processor, cia,
3874 *frA, *frC,
3875 fpscr_vxsnan | fpscr_vximz,
3876 1, /*single?*/
3877 0) /*negate?*/) {
3878 invalid_arithemetic_operation(processor, cia,
3879 (unsigned64*)&product, *frA, 0, *frC,
3880 0, /*instruction_is_frsp*/
3881 0, /*instruction_is_convert_to_64bit*/
3882 0, /*instruction_is_convert_to_32bit*/
3883 0); /*single-precision*/
3884 }
3885 else {
3886 /*HACK!*/
3887 product = *(double*)frA * *(double*)frC;
3888 }
3889 /* compute the add */
3890 if (is_invalid_operation(processor, cia,
3891 product, *frB,
3892 fpscr_vxsnan | fpscr_vxisi,
3893 1, /*single?*/
3894 0) /*negate?*/) {
3895 invalid_arithemetic_operation(processor, cia,
3896 frT, product, *frB, 0,
3897 0, /*instruction_is_frsp*/
3898 0, /*instruction_is_convert_to_64bit*/
3899 0, /*instruction_is_convert_to_32bit*/
3900 0); /*single-precision*/
3901 }
3902 else {
3903 /*HACK!*/
3904 float s = -(product + *(double*)frB);
3905 *(double*)frT = (double)s;
3906 }
3907 FPSCR_END(Rc);
3908 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
3909
3910 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract
3911 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3912 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3913 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3914 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3915 FPSCR_BEGIN;
3916 double product; /*HACK! - incorrectly loosing precision ... */
3917 /* compute the multiply */
3918 if (is_invalid_operation(processor, cia,
3919 *frA, *frC,
3920 fpscr_vxsnan | fpscr_vximz,
3921 0, /*single?*/
3922 0) /*negate?*/) {
3923 invalid_arithemetic_operation(processor, cia,
3924 (unsigned64*)&product, *frA, 0, *frC,
3925 0, /*instruction_is_frsp*/
3926 0, /*instruction_is_convert_to_64bit*/
3927 0, /*instruction_is_convert_to_32bit*/
3928 0); /*single-precision*/
3929 }
3930 else {
3931 /*HACK!*/
3932 product = *(double*)frA * *(double*)frC;
3933 }
3934 /* compute the subtract */
3935 if (is_invalid_operation(processor, cia,
3936 product, *frB,
3937 fpscr_vxsnan | fpscr_vxisi,
3938 0, /*single?*/
3939 0) /*negate?*/) {
3940 invalid_arithemetic_operation(processor, cia,
3941 frT, product, *frB, 0,
3942 0, /*instruction_is_frsp*/
3943 0, /*instruction_is_convert_to_64bit*/
3944 0, /*instruction_is_convert_to_32bit*/
3945 0); /*single-precision*/
3946 }
3947 else {
3948 /*HACK!*/
3949 double s = -(product - *(double*)frB);
3950 *(double*)frT = s;
3951 }
3952 FPSCR_END(Rc);
3953 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
3954
3955 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract Single
3956 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3957 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3958 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3959 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3960 FPSCR_BEGIN;
3961 float product; /*HACK! - incorrectly loosing precision ... */
3962 /* compute the multiply */
3963 if (is_invalid_operation(processor, cia,
3964 *frA, *frC,
3965 fpscr_vxsnan | fpscr_vximz,
3966 1, /*single?*/
3967 0) /*negate?*/) {
3968 invalid_arithemetic_operation(processor, cia,
3969 (unsigned64*)&product, *frA, 0, *frC,
3970 0, /*instruction_is_frsp*/
3971 0, /*instruction_is_convert_to_64bit*/
3972 0, /*instruction_is_convert_to_32bit*/
3973 0); /*single-precision*/
3974 }
3975 else {
3976 /*HACK!*/
3977 product = *(double*)frA * *(double*)frC;
3978 }
3979 /* compute the subtract */
3980 if (is_invalid_operation(processor, cia,
3981 product, *frB,
3982 fpscr_vxsnan | fpscr_vxisi,
3983 1, /*single?*/
3984 0) /*negate?*/) {
3985 invalid_arithemetic_operation(processor, cia,
3986 frT, product, *frB, 0,
3987 0, /*instruction_is_frsp*/
3988 0, /*instruction_is_convert_to_64bit*/
3989 0, /*instruction_is_convert_to_32bit*/
3990 0); /*single-precision*/
3991 }
3992 else {
3993 /*HACK!*/
3994 float s = -(product - *(double*)frB);
3995 *(double*)frT = (double)s;
3996 }
3997 FPSCR_END(Rc);
3998 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
3999
4000
4001 #
4002 # I.4.6.6 Floating-Point Rounding and Conversion Instructions
4003 #
4004
4005 0.63,6.FRT,11./,16.FRB,21.12,31.Rc:X:f::Floating Round to Single-Precision
4006 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4007 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4008 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4009 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4010 int sign;
4011 int exp;
4012 unsigned64 frac_grx;
4013 enum { start, finish, Disabled_Exponent_Underflow, Enabled_Exponent_Underflow, Disabled_Exponent_Overflow, Enabled_Exponent_Overflow, Normal_Operand, Zero_Operand, Infinity_Operand, QNaN_Operand, SNaN_Operand, Enabled_Overflow, Done } label = start;
4014 while (label != finish) switch (label) {
4015 case finish:
4016 error("Unhandled switch\n");
4017 case start:
4018 /* split off cases for what to do */
4019 if (EXTRACTED64(*frB, 1, 11) < 897
4020 && EXTRACTED64(*frB, 1, 63) > 0) {
4021 if ((FPSCR & fpscr_ue) == 0) { label = Disabled_Exponent_Underflow; break; }
4022 if ((FPSCR & fpscr_ue) != 0) { label = Enabled_Exponent_Underflow; break; }
4023 }
4024 if (EXTRACTED64(*frB, 1, 11) > 1150
4025 && EXTRACTED64(*frB, 1, 11) < 2047) {
4026 if ((FPSCR & fpscr_oe) == 0) { label = Disabled_Exponent_Overflow; break; }
4027 if ((FPSCR & fpscr_oe) != 0) { label = Enabled_Exponent_Overflow; break; }
4028 }
4029 if (EXTRACTED64(*frB, 1, 11) > 896
4030 && EXTRACTED64(*frB, 1, 11) < 1151) { label = Normal_Operand; break; }
4031 if (EXTRACTED64(*frB, 1, 63) == 0) { label = Zero_Operand; break; }
4032 if (EXTRACTED64(*frB, 1, 11) == 2047) {
4033 if (EXTRACTED64(*frB, 12, 63) == 0) { label = Infinity_Operand; break; }
4034 if (EXTRACTED64(*frB, 12, 12) == 1) { label = QNaN_Operand; break; }
4035 if (EXTRACTED64(*frB, 12, 12) == 0
4036 && EXTRACTED64(*frB, 13, 63) > 0) { label = SNaN_Operand; break; }
4037 }
4038 case Disabled_Exponent_Underflow:
4039 sign = EXTRACTED64(*frB, 0, 0);
4040 if (EXTRACTED64(*frB, 1, 11) == 0) {
4041 exp = -1022;
4042 frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4043 }
4044 if (EXTRACTED64(*frB, 1, 11) > 0) {
4045 exp = EXTRACTED64(*frB, 1, 11) - 1023;
4046 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4047 }
4048 /* G|R|X == zero from above */
4049 while (exp < -126) {
4050 exp = exp - 1;
4051 frac_grx = (INSERTED64(EXTRACTED64(frac_grx, 0, 54), 1, 55)
4052 | MASKED64(frac_grx, 55, 55));
4053 }
4054 FPSCR_SET_UX(EXTRACTED64(frac_grx, 24, 55) > 0);
4055 Round_Single(processor, sign, &exp, &frac_grx);
4056 FPSCR_SET_XX(FPSCR & fpscr_fi);
4057 if (EXTRACTED64(frac_grx, 0, 52) == 0) {
4058 *frT = INSERTED64(sign, 0, 0);
4059 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
4060 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
4061 }
4062 if (EXTRACTED64(frac_grx, 0, 52) > 0) {
4063 if (EXTRACTED64(frac_grx, 0, 0) == 1) {
4064 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4065 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4066 }
4067 if (EXTRACTED64(frac_grx, 0, 0) == 0) {
4068 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_denormalized_number);
4069 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_denormalized_number);
4070 }
4071 /*Normalize_Operand:*/
4072 while (EXTRACTED64(frac_grx, 0, 0) == 0) {
4073 exp = exp - 1;
4074 frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1, 52), 0, 51);
4075 }
4076 *frT = (INSERTED64(sign, 0, 0)
4077 | INSERTED64(exp + 1023, 1, 11)
4078 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4079 }
4080 { label = Done; break; }
4081 case Enabled_Exponent_Underflow:
4082 FPSCR_SET_UX(1);
4083 sign = EXTRACTED64(*frB, 0, 0);
4084 if (EXTRACTED64(*frB, 1, 11) == 0) {
4085 exp = -1022;
4086 frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4087 }
4088 if (EXTRACTED64(*frB, 1, 11) > 0) {
4089 exp = EXTRACTED64(*frB, 1, 11) - 1023;
4090 frac_grx = (BIT64(0) |
4091 INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52));
4092 }
4093 /*Normalize_Operand:*/
4094 while (EXTRACTED64(frac_grx, 0, 0) == 0) {
4095 exp = exp - 1;
4096 frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1, 52), 0, 51);
4097 }
4098 Round_Single(processor, sign, &exp, &frac_grx);
4099 FPSCR_SET_XX(FPSCR & fpscr_fi);
4100 exp = exp + 192;
4101 *frT = (INSERTED64(sign, 0, 0)
4102 | INSERTED64(exp + 1023, 1, 11)
4103 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4104 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4105 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4106 { label = Done; break; }
4107 case Disabled_Exponent_Overflow:
4108 FPSCR_SET_OX(1);
4109 if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
4110 if (EXTRACTED64(*frB, 0, 0) == 0) {
4111 *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
4112 FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
4113 }
4114 if (EXTRACTED64(*frB, 0, 0) == 1) {
4115 *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
4116 FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
4117 }
4118 }
4119 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_zero) {
4120 if (EXTRACTED64(*frB, 0, 0) == 0) {
4121 *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
4122 FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4123 }
4124 if (EXTRACTED64(*frB, 0, 0) == 1) {
4125 *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
4126 FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4127 }
4128 }
4129 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_pos_infinity) {
4130 if (EXTRACTED64(*frB, 0, 0) == 0) {
4131 *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
4132 FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
4133 }
4134 if (EXTRACTED64(*frB, 0, 0) == 1) {
4135 *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
4136 FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4137 }
4138 }
4139 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_neg_infinity) {
4140 if (EXTRACTED64(*frB, 0, 0) == 0) {
4141 *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
4142 FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4143 }
4144 if (EXTRACTED64(*frB, 0, 0) == 1) {
4145 *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
4146 FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
4147 }
4148 }
4149 /* FPSCR[FR] <- undefined */
4150 FPSCR_SET_FI(1);
4151 FPSCR_SET_XX(1);
4152 { label = Done; break; }
4153 case Enabled_Exponent_Overflow:
4154 sign = EXTRACTED64(*frB, 0, 0);
4155 exp = EXTRACTED64(*frB, 1, 11) - 1023;
4156 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4157 Round_Single(processor, sign, &exp, &frac_grx);
4158 FPSCR_SET_XX(FPSCR & fpscr_fi);
4159 case Enabled_Overflow:
4160 FPSCR_SET_OX(1);
4161 exp = exp - 192;
4162 *frT = (INSERTED64(sign, 0, 0)
4163 | INSERTED64(exp + 1023, 1, 11)
4164 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4165 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4166 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4167 { label = Done; break; }
4168 case Zero_Operand:
4169 *frT = *frB;
4170 if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
4171 if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
4172 FPSCR_SET_FR(0);
4173 FPSCR_SET_FI(0);
4174 { label = Done; break; }
4175 case Infinity_Operand:
4176 *frT = *frB;
4177 if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
4178 if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
4179 FPSCR_SET_FR(0);
4180 FPSCR_SET_FI(0);
4181 { label = Done; break; }
4182 case QNaN_Operand:
4183 *frT = INSERTED64(EXTRACTED64(*frB, 0, 34), 0, 34);
4184 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
4185 FPSCR_SET_FR(0);
4186 FPSCR_SET_FI(0);
4187 { label = Done; break; }
4188 case SNaN_Operand:
4189 FPSCR_OR_VX(fpscr_vxsnan);
4190 if ((FPSCR & fpscr_ve) == 0) {
4191 *frT = (MASKED64(*frB, 0, 11)
4192 | BIT64(12)
4193 | MASKED64(*frB, 13, 34));
4194 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
4195 }
4196 FPSCR_SET_FR(0);
4197 FPSCR_SET_FI(0);
4198 { label = Done; break; }
4199 case Normal_Operand:
4200 sign = EXTRACTED64(*frB, 0, 0);
4201 exp = EXTRACTED64(*frB, 1, 11) - 1023;
4202 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4203 Round_Single(processor, sign, &exp, &frac_grx);
4204 FPSCR_SET_XX(FPSCR & fpscr_fi);
4205 if (exp > 127 && (FPSCR & fpscr_oe) == 0) { label = Disabled_Exponent_Overflow; break; }
4206 if (exp > 127 && (FPSCR & fpscr_oe) != 0) { label = Enabled_Overflow; break; }
4207 *frT = (INSERTED64(sign, 0, 0)
4208 | INSERTED64(exp + 1023, 1, 11)
4209 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4210 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4211 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4212 { label = Done; break; }
4213 case Done:
4214 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
4215 { label = finish; break; }
4216 }
4217
4218 0.63,6.FRT,11./,16.FRB,21.814,31.Rc:X:64,f::Floating Convert To Integer Doubleword
4219
4220 0.63,6.FRT,11./,16.FRB,21.815,31.Rc:X:64,f::Floating Convert To Integer Doubleword with round towards Zero
4221
4222 0.63,6.FRT,11./,16.FRB,21.14,31.Rc:X:f::Floating Convert To Integer Word
4223
4224 0.63,6.FRT,11./,16.FRB,21.15,31.Rc:X:f:fctiwz:Floating Convert To Integer Word with round towards Zero
4225 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4226 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4227 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4228 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4229 FPSCR_BEGIN;
4230 convert_to_integer(processor, cia,
4231 frT, *frB,
4232 fpscr_rn_round_towards_zero, 32);
4233 FPSCR_END(Rc);
4234 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
4235
4236 0.63,6.FRT,11./,16.FRB,21.846,31.Rc:X:64,f::Floating Convert from Integer Doubleword
4237 int sign = EXTRACTED64(*frB, 0, 0);
4238 int exp = 63;
4239 unsigned64 frac = *frB;
4240 enum { start, finish, Zero_Operand, Done } label = start;
4241 while (label != finish) switch (label) {
4242 case finish:
4243 error("Unhandled switch\n");
4244 case start:
4245 if (frac == 0) { label = Zero_Operand; break; }
4246 if (sign == 1) frac = ~frac + 1;
4247 while (EXTRACTED64(frac, 0, 0) == 0) {
4248 /*??? do the loop 0 times if (FRB) = max negative integer */
4249 frac = INSERTED64(EXTRACTED64(frac, 1, 63), 0, 62);
4250 exp = exp - 1;
4251 }
4252 Round_Float(processor, sign, &exp, &frac, FPSCR & fpscr_rn);
4253 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4254 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4255 *frT = (INSERTED64(sign, 0, 0)
4256 | INSERTED64(exp + 1023, 1, 11)
4257 | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
4258 { label = Done; break; }
4259 /**/
4260 case Zero_Operand:
4261 FPSCR_SET_FR(0);
4262 FPSCR_SET_FI(0);
4263 FPSCR_SET_FPRF(fpscr_rf_pos_zero);
4264 *frT = 0;
4265 { label = Done; break; }
4266 /**/
4267 case Done:
4268 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
4269 { label = finish; break; }
4270 }
4271
4272 #
4273 # I.4.6.7 Floating-Point Compare Instructions
4274 #
4275
4276 0.63,6.BF,9./,11.FRA,16.FRB,21.0,31./:X:f:fcmpu:Floating Compare Unordered
4277 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4278 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4279 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4280 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4281 FPSCR_BEGIN;
4282 unsigned c;
4283 if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
4284 c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
4285 else if (is_less_than(frA, frB))
4286 c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
4287 else if (is_greater_than(frA, frB))
4288 c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
4289 else
4290 c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
4291 FPSCR_SET_FPCC(c);
4292 CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
4293 if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0))
4294 FPSCR_OR_VX(fpscr_vxsnan);
4295 FPSCR_END(0);
4296 PPC_INSN_FLOAT_CR(0, FRA_BITMASK | FRB_BITMASK, BF_BITMASK);
4297
4298 0.63,6.BF,9./,11.FRA,16.FRB,21.32,31./:X:f:fcmpo:Floating Compare Ordered
4299 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4300 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4301 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4302 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4303 FPSCR_BEGIN;
4304 unsigned c;
4305 if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
4306 c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
4307 else if (is_less_than(frA, frB))
4308 c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
4309 else if (is_greater_than(frA, frB))
4310 c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
4311 else
4312 c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
4313 FPSCR_SET_FPCC(c);
4314 CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
4315 if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0)) {
4316 FPSCR_OR_VX(fpscr_vxsnan);
4317 if ((FPSCR & fpscr_ve) == 0)
4318 FPSCR_OR_VX(fpscr_vxvc);
4319 }
4320 else if (is_QNaN(*frA, 0) || is_QNaN(*frB, 0)) {
4321 FPSCR_OR_VX(fpscr_vxvc);
4322 }
4323 FPSCR_END(0);
4324 PPC_INSN_FLOAT_CR(0, FRA_BITMASK | FRB_BITMASK, BF_BITMASK);
4325
4326
4327 #
4328 # I.4.6.8 Floating-Point Status and Control Register Instructions
4329 #
4330
4331 0.63,6.FRT,11./,16./,21.583,31.Rc:X:f::Move From FPSCR
4332
4333 0.63,6.BF,9./,11.BFA,14./,16./,21.64,31./:X:f::Move to Condition Register from FPSCR
4334
4335 0.64,6.BF,9./,11./,16.U,20./,21.134,31.Rc:X:f::Move To FPSCR Field Immediate
4336
4337 0.63,6./,7.FLM,15./,16.FRB,21.711,31.Rc:XFL:f::Move To FPSCR Fields
4338
4339 0.63,6.BT,11./,16./,21.70,31.Rc:X:f::Move To FPSCR Bit 0
4340
4341 0.63,6.BT,11./,16./,21.38,31.Rc:X:f::Move To FPSCR Bit 1
4342
4343
4344 #
4345 # I.A.1.1 Floating-Point Store Instruction
4346 #
4347 0.31,6.FRS,11.RA,16.RB,21.983,31./:X:f::Store Floating-Point as Integer Word Indexed
4348
4349 #
4350 # I.A.1.2 Floating-Point Arithmetic Instructions
4351 #
4352
4353 0.63,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f::Floating Square Root
4354
4355 0.59,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f::Floating Square Root Single
4356
4357 0.59,6.FRT,11./,16.FRB,21./,26.24,31.Rc:A:f::Floating Reciprocal Estimate Single
4358
4359 0.63,6.FRT,11./,16.FRB,21./,26.26,31.Rc:A:f::Floating Reciprocal Square Root Estimate
4360
4361 #
4362 # I.A.1.3 Floating-Point Select Instruction
4363 #
4364
4365 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.23,31.Rc:A:f::Floating Select
4366
4367
4368 #
4369 # II.3.2 Cache Management Instructions
4370 #
4371
4372 0.31,6./,11.RA,16.RB,21.982,31./:X::icbi:Instruction Cache Block Invalidate
4373 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4374 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4375 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4376 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
4377 /* blindly flush all instruction cache entries */
4378 #if WITH_IDECODE_CACHE_SIZE
4379 cpu_flush_icache(processor);
4380 #endif
4381 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0);
4382
4383 0.19,6./,11./,16./,21.150,31./:XL::isync:Instruction Synchronize
4384 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4385 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4386 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4387 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
4388 cpu_synchronize_context(processor);
4389 PPC_INSN_INT(0, 0, 0);
4390
4391
4392 #
4393 # II.3.2.2 Data Cache Instructions
4394 #
4395
4396 0.31,6./,11.RA,16.RB,21.278,31./:X:::Data Cache Block Touch
4397 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4398 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4399 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4400 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
4401 TRACE(trace_tbd,("Data Cache Block Touch\n"));
4402 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4403
4404 0.31,6./,11.RA,16.RB,21.246,31./:X:::Data Cache Block Touch for Store
4405 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4406 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4407 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4408 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4409 TRACE(trace_tbd,("Data Cache Block Touch for Store\n"));
4410 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4411
4412 0.31,6./,11.RA,16.RB,21.1014,31./:X:::Data Cache Block set to Zero
4413 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4414 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 10, 10, 0
4415 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 10, 10, 0
4416 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4417 TRACE(trace_tbd,("Data Cache Block set to Zero\n"));
4418 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4419
4420 0.31,6./,11.RA,16.RB,21.54,31./:X:::Data Cache Block Store
4421 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4422 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
4423 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
4424 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
4425 TRACE(trace_tbd,("Data Cache Block Store\n"));
4426 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4427
4428 0.31,6./,11.RA,16.RB,21.86,31./:X:::Data Cache Block Flush
4429 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4430 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
4431 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
4432 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
4433 TRACE(trace_tbd,("Data Cache Block Flush\n"));
4434 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4435
4436 #
4437 # II.3.3 Enforce In-order Execution of I/O Instruction
4438 #
4439
4440 0.31,6./,11./,16./,21.854,31./:X::eieio:Enforce In-order Execution of I/O
4441 /* Since this model has no instruction overlap
4442 this instruction need do nothing */
4443
4444 #
4445 # II.4.1 Time Base Instructions
4446 #
4447
4448 0.31,6.RT,11.tbr,21.371,31./:XFX::mftb:Move From Time Base
4449 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
4450 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
4451 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
4452 int n = (tbr{5:9} << 5) | tbr{0:4};
4453 if (n == 268) {
4454 if (is_64bit_implementation) *rT = TB;
4455 else *rT = EXTRACTED64(TB, 32, 63);
4456 }
4457 else if (n == 269) {
4458 if (is_64bit_implementation) *rT = EXTRACTED64(TB, 0, 31);
4459 else *rT = EXTRACTED64(TB, 0, 31);
4460 }
4461 else
4462 program_interrupt(processor, cia,
4463 illegal_instruction_program_interrupt);
4464
4465
4466 #
4467 # III.2.3.1 System Linkage Instructions
4468 #
4469
4470 0.19,6./,11./,16./,21.50,31./:XL::rfi:Return From Interrupt
4471 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4472 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4473 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4474 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
4475 if (IS_PROBLEM_STATE(processor)) {
4476 program_interrupt(processor, cia,
4477 privileged_instruction_program_interrupt);
4478 }
4479 else {
4480 MSR = (MASKED(SRR1, 0, 32)
4481 | MASKED(SRR1, 37, 41)
4482 | MASKED(SRR1, 48, 63));
4483 NIA = MASKED(SRR0, 0, 61);
4484 cpu_synchronize_context(processor);
4485 check_masked_interrupts(processor);
4486 }
4487
4488 #
4489 # III.3.4.1 Move to/from System Register Instructions
4490 #
4491
4492 #0.31,6.RS,11.SPR,21.467,31./:XFX:::Move To Special Purpose Register
4493 #0.31,6.RT,11.SPR,21.339,31./:XFX:::Move From Special Purpose Register
4494 0.31,6.RS,11./,16./,21.146,31./:X:::Move To Machine State Register
4495 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4496 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4497 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4498 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4499 if (IS_PROBLEM_STATE(processor))
4500 program_interrupt(processor, cia,
4501 privileged_instruction_program_interrupt);
4502 else {
4503 MSR = *rS;
4504 check_masked_interrupts(processor);
4505 }
4506
4507 0.31,6.RT,11./,16./,21.83,31./:X:::Move From Machine State Register
4508 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4509 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
4510 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
4511 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
4512 if (IS_PROBLEM_STATE(processor))
4513 program_interrupt(processor, cia,
4514 privileged_instruction_program_interrupt);
4515 else {
4516 *rT = MSR;
4517 check_masked_interrupts(processor);
4518 }
4519
4520
4521 #
4522 # III.4.11.1 Cache Management Instructions
4523 #
4524
4525 0.31,6./,11.RA,16.RB,21.470,31./:X::dcbi:Data Cache Block Invalidate
4526 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4527 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4528 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4529 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4530 if (IS_PROBLEM_STATE(processor))
4531 program_interrupt(processor, cia,
4532 privileged_instruction_program_interrupt);
4533 else
4534 TRACE(trace_tbd,("Data Cache Block Invalidate\n"));
4535
4536 #
4537 # III.4.11.2 Segment Register Manipulation Instructions
4538 #
4539
4540 0.31,6.RS,11./,12.SR,16./,21.210,31./:X:32:mtsr %SR,%RS:Move To Segment Register
4541 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4542 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4543 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4544 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4545 if (IS_PROBLEM_STATE(processor))
4546 program_interrupt(processor, cia,
4547 privileged_instruction_program_interrupt);
4548 else
4549 SEGREG(SR) = *rS;
4550
4551 0.31,6.RS,11./,16.RB,21.242,31./:X:32:mtsrin %RS,%RB:Move To Segment Register Indirect
4552 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4553 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4554 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4555 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4556 if (IS_PROBLEM_STATE(processor))
4557 program_interrupt(processor, cia,
4558 privileged_instruction_program_interrupt);
4559 else
4560 SEGREG(EXTRACTED32(*rB, 0, 3)) = *rS;
4561
4562 0.31,6.RT,11./,12.SR,16./,21.595,31./:X:32:mfsr %RT,%RS:Move From Segment Register
4563 *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
4564 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4565 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4566 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4567 if (IS_PROBLEM_STATE(processor))
4568 program_interrupt(processor, cia,
4569 privileged_instruction_program_interrupt);
4570 else
4571 *rT = SEGREG(SR);
4572
4573 0.31,6.RT,11./,16.RB,21.659,31./:X:32:mfsrin %RT,%RB:Move From Segment Register Indirect
4574 *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
4575 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4576 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4577 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4578 if (IS_PROBLEM_STATE(processor))
4579 program_interrupt(processor, cia,
4580 privileged_instruction_program_interrupt);
4581 else
4582 *rT = SEGREG(EXTRACTED32(*rB, 0, 3));
4583
4584
4585 #
4586 # III.4.11.3 Lookaside Buffer Management Instructions (Optional)
4587 #
4588
4589 0.31,6./,11./,16.RB,21.434,31./:X:64::SLB Invalidate Entry
4590
4591 0.31,6./,11./,16./,21.498,31./:X:64::SLB Invalidate All
4592
4593 0.31,6./,11./,16.RB,21.306,31./:X:::TLB Invalidate Entry
4594 if (IS_PROBLEM_STATE(processor))
4595 program_interrupt(processor, cia,
4596 privileged_instruction_program_interrupt);
4597 else {
4598 int nr = 0;
4599 cpu *proc;
4600 while (1) {
4601 proc = psim_cpu(cpu_system(processor), nr);
4602 if (proc == NULL) break;
4603 cpu_page_tlb_invalidate_entry(proc, *rB);
4604 nr++;
4605 }
4606 }
4607
4608 0.31,6./,11./,16./,21.370,31./:X:::TLB Invalidate All
4609 if (IS_PROBLEM_STATE(processor))
4610 program_interrupt(processor, cia,
4611 privileged_instruction_program_interrupt);
4612 else {
4613 int nr = 0;
4614 cpu *proc;
4615 while (1) {
4616 proc = psim_cpu(cpu_system(processor), nr);
4617 if (proc == NULL) break;
4618 cpu_page_tlb_invalidate_all(proc);
4619 nr++;
4620 }
4621 }
4622
4623 0.31,6./,11./,16./,21.566,31./:X:::TLB Synchronize
4624 /* nothing happens here - always in sync */
4625
4626 #
4627 # III.A.1.2 External Access Instructions
4628 #
4629
4630 0.31,6.RT,11.RA,16.RB,21.310,31./:X:earwax::External Control In Word Indexed
4631
4632 0.31,6.RS,11.RA,16.RB,21.438,31./:X:earwax::External Control Out Word Indexed
This page took 0.127944 seconds and 4 git commands to generate.