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