2 # This file is part of the program psim.
4 # Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
8 # The pseudo-code that appears below, translated into C, was copied
9 # by Andrew Cagney of Moss Vale, Australia.
11 # This pseudo-code is copied by permission from the publication
12 # "The PowerPC Architecture: A Specification for A New Family of
13 # RISC Processors" (ISBN 1-55860-316-6) copyright 1993, 1994 by
14 # International Business Machines Corporation.
16 # THIS PERMISSION IS PROVIDED WITHOUT WARRANTY OF ANY KIND, EITHER
17 # EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES
18 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22 # This program is free software; you can redistribute it and/or modify
23 # it under the terms of the GNU General Public License as published by
24 # the Free Software Foundation; either version 2 of the License, or
25 # (at your option) any later version.
27 # This program is distributed in the hope that it will be useful,
28 # but WITHOUT ANY WARRANTY; without even the implied warranty of
29 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 # GNU General Public License for more details.
32 # You should have received a copy of the GNU General Public License
33 # along with this program; if not, write to the Free Software
34 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
41 # 1 Instruction format as a `start-bit,content' pairs.
42 # the content is one of a digit, field name or `/' (aka.0)
46 # 3 Flags: 64 - 64bit only
47 # f - floating point enabled required
54 # For flags marked 'model', the fields are interpreted as follows:
62 # 4 String name for model
64 # 5 Specific CPU model, must be an identifier
66 # 6 Comma separated list of functional units
69 ::model:604:ppc604: PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0
70 ::model:603e:ppc603e:PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0
71 ::model:603:ppc603: PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0
72 ::model:601:ppc601: PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0
76 typedef enum _ppc_function_unit {
77 PPC_UNIT_BAD, /* unknown function unit */
78 PPC_UNIT_IU, /* integer unit (601/603 style) */
79 PPC_UNIT_SRU, /* system register unit (601/603 style) */
80 PPC_UNIT_SCIU1, /* 1st single cycle integer unit (604 style) */
81 PPC_UNIT_SCIU2, /* 2nd single cycle integer unit (604 style) */
82 PPC_UNIT_MCIU, /* multiple cycle integer unit (604 style) */
83 PPC_UNIT_FPU, /* floating point unit */
84 PPC_UNIT_LSU, /* load/store unit */
85 PPC_UNIT_BPU, /* branch unit */
89 /* Structure to hold timing information on a per instruction basis */
91 ppc_function_unit first_unit; /* first functional unit this insn could use */
92 ppc_function_unit last_unit; /* last functional unit this insn could use */
93 signed16 issue; /* # cycles before function unit can process other insns */
94 signed16 done; /* # cycles before insn is done */
95 unsigned32 flags; /* any flags that are needed */
98 /* Register mappings */
99 #define PPC_INT_REG 0 /* start of integer registers */
100 #define PPC_FLOAT_REG (PPC_INT_REG + 32) /* start of floating point registers */
101 #define PPC_CR_REG (PPC_FLOAT_REG + 32) /* start of CR0 .. CR7 */
102 #define PPC_SPR_REG (PPC_CR_REG + 8) /* start of special purpose registers */
103 #define PPC_FPSCR_REG (PPC_SPR_REG + 1024) /* start of fpscr register */
104 #define NR_PPC_REGS (PPC_FPSCR_REG + 1) /* # of registers to allocate */
106 /* Structure for each register to indicate whether it is free or not */
107 typedef struct _model_reg model_reg;
109 model_reg *next; /* next register to be released */
110 int in_use; /* non zero if register is used */
113 /* Structure for each functional unit that is busy */
114 typedef struct _model_busy model_busy;
116 model_busy *next; /* next function unit */
117 model_reg *reg; /* list of registers to release */
118 ppc_function_unit unit; /* function unit name */
119 signed16 issue; /* # of cycles until unit can accept another insn */
120 signed16 done; /* # of cycles until insn is done */
123 /* Structure to hold the current state information for the simulated CPU model */
125 cpu *processor; /* point back to processor */
126 const char *name; /* model name */
127 const model_time *timing; /* timing information */
128 model_busy *busy_list; /* list of busy function units */
129 model_busy *free_list; /* list of model_busy structs not in use */
130 model_reg registers[NR_PPC_REGS]; /* register status */
131 unsigned32 busy_mask; /* bitmask of busy function units */
132 count_type nr_cycles; /* # cycles */
133 count_type nr_branches; /* # branches */
134 count_type nr_branches_fallthrough; /* # conditional branches that fell through */
135 count_type nr_branch_predict_trues; /* # branches predicted correctly */
136 count_type nr_branch_predict_falses; /* # branches predicted incorrectly */
137 count_type nr_stalls_data; /* # of stalls for data */
138 count_type nr_stalls_unit; /* # of stalls waiting for a function unit */
139 count_type nr_stalls_serialize; /* # of stalls waiting for things to quiet down */
140 count_type nr_insns_not_handled; /* # of instructions not handled */
141 count_type nr_units[nr_ppc_function_units]; /* function unit counts */
142 int insn_handled; /* whether last insn was handled */
145 STATIC_MODEL const char *const ppc_function_unit_name[ (int)nr_ppc_function_units ] = {
146 "unknown functional unit instruction",
147 "integer functional unit instruction",
148 "system register functional unit instruction",
149 "1st single cycle integer functional unit instruction",
150 "2nd single cycle integer functional unit instruction",
151 "multiple cycle integer functional unit instruction",
152 "floating point functional unit instruction",
153 "load/store functional unit instruction",
154 "branch functional unit instruction",
157 # Code called after executing the semantics of the function
158 void::model-function::model_cleanup:itable_index index, model_data *model_ptr
159 if (model_ptr->insn_handled)
160 model_ptr->insn_handled = 0;
162 model_ptr->nr_insns_not_handled++;
163 TRACE(trace_tbd,("model specific code for %s not done\n", itable[index].name));
166 # Advance state to next cycle, releasing any registers allocated
167 void::model-internal::model_new_cycle:model_data *model_ptr
168 model_busy *cur_busy = model_ptr->busy_list;
169 model_busy *free_list = model_ptr->free_list;
170 model_busy *next_busy = (model_busy *)0;
171 unsigned32 busy_mask = model_ptr->busy_mask;
174 model_ptr->nr_cycles++;
175 for ( ; cur_busy; cur_busy = next) {
176 next = cur_busy->next;
177 if (--cur_busy->done <= 0) { /* function unit done, release registers */
178 model_reg *reg = cur_busy->reg;
179 TRACE(trace_model,("done, retiring %s\n", ppc_function_unit_name[cur_busy->unit]));
181 TRACE(trace_model,("freeing up reg, address 0x%lx (%d)\n", (long)reg, reg - &model_ptr->registers[0]));
185 busy_mask &= ~(1 << cur_busy->unit);
186 cur_busy->next = free_list;
187 free_list = cur_busy;
189 else if (--cur_busy->issue <= 0) { /* function unit pipelined, allow new use */
190 TRACE(trace_model,("pipeline, %s ready for next client\n", ppc_function_unit_name[cur_busy->unit]));
191 busy_mask &= ~(1 << cur_busy->unit);
192 cur_busy->next = next_busy;
193 next_busy = cur_busy;
196 TRACE(trace_model,("%s still working, issue = %d, done = %d\n",
197 ppc_function_unit_name[cur_busy->unit],
200 cur_busy->next = next_busy;
201 next_busy = cur_busy;
205 model_ptr->busy_list = next_busy;
206 model_ptr->free_list = free_list;
207 model_ptr->busy_mask = busy_mask;
209 # Mark a function unit as busy, return the busy structure so regs can be added to be released
210 model_busy *::model-internal::model_make_busy:model_data *model_ptr, ppc_function_unit unit, int issue, int done
213 TRACE(trace_model,("unit = %s, issue = %d, done = %d\n", ppc_function_unit_name[unit], issue, done));
214 model_ptr->insn_handled = 1;
216 if (!model_ptr->free_list) {
217 busy = ZALLOC(model_busy);
220 busy = model_ptr->free_list;
221 model_ptr->free_list = busy->next;
222 busy->reg = (model_reg *)0;
224 busy->next = model_ptr->busy_list;
228 model_ptr->busy_list = busy;
229 model_ptr->busy_mask |= (1 << unit);
230 model_ptr->nr_units[unit]++;
233 # Wait until a function unit is non-busy, and then allocate a busy pointer & return the pointer
234 model_busy *::model-internal::model_wait_for_unit:itable_index index, model_data *const model_ptr, const model_time *const time_ptr
235 ppc_function_unit first_unit = time_ptr->first_unit;
236 ppc_function_unit last_unit = time_ptr->last_unit;
237 ppc_function_unit unit;
238 int stall_increment = 0;
241 unsigned32 busy_mask = model_ptr->busy_mask;
242 for (unit = first_unit; unit <= last_unit; unit++) {
243 if (((1 << unit) & busy_mask) == 0) {
244 return model_make_busy(model_ptr, unit,
245 model_ptr->timing[index].issue,
246 model_ptr->timing[index].done);
250 TRACE(trace_model,("all function units are busy for %s\n", itable[index].name));
251 model_ptr->nr_stalls_unit += stall_increment; /* don't count first stall */
253 model_new_cycle(model_ptr);
256 # Serialize the processor, waiting for all instructions to drain out before adding an instruction.
257 void::model-function::model_serialize:itable_index index, model_data *model_ptr
258 while (model_ptr->busy_list) {
259 TRACE(trace_model,("waiting for pipeline to empty\n"));
260 model_ptr->nr_stalls_serialize++;
261 model_new_cycle(model_ptr);
263 (void) model_make_busy(model_ptr,
264 model_ptr->timing[index].first_unit,
265 model_ptr->timing[index].issue,
266 model_ptr->timing[index].done);
268 # Wait for a CR to become unbusy
269 void::model-function::model_wait_for_cr:model_data *model_ptr, unsigned CRBIT
272 for (u = 0xc0000000; (u != 0) && (CRBIT & u) == 0; u >>= 4 )
275 while (model_ptr->registers[cr_var + PPC_CR_REG].in_use) {
276 TRACE(trace_model,("waiting for CR %d\n", cr_var));
277 model_ptr->nr_stalls_data++;
278 model_new_cycle(model_ptr);
281 # Schedule an instruction that takes 2 integer input registers and produces an output register & possibly sets CR0
282 void::model-function::ppc_insn_int2:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rD, signed_word *rA, signed_word *rB, unsigned Rc
283 if (!WITH_MODEL_ISSUE)
287 registers *cpu_regs = cpu_registers(processor);
288 const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
289 const unsigned ppc_RB = (rB - &cpu_regs->gpr[0]) + PPC_INT_REG;
290 const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
291 model_reg *ppc_regs = model_ptr->registers;
292 model_busy *busy_ptr;
294 if (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
295 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
297 while (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
298 model_ptr->nr_stalls_data++;
299 model_new_cycle(model_ptr);
303 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
304 ppc_regs[ppc_RD].next = (model_reg *)0;
305 ppc_regs[ppc_RD].in_use = 1;
307 busy_ptr->reg = &ppc_regs[ppc_RD];
309 model_reg *reg_CR0 = &ppc_regs[0 + PPC_CR_REG];
310 reg_CR0->next = &ppc_regs[ppc_RD];
311 busy_ptr->reg = reg_CR0;
315 # Schedule an instruction that takes 1 integer input registers and produces an output register & possibly sets CR0
316 void::model-function::ppc_insn_int1:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rD, signed_word *rA, unsigned Rc
317 if (!WITH_MODEL_ISSUE)
321 registers *cpu_regs = cpu_registers(processor);
322 const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
323 const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
324 model_reg *ppc_regs = model_ptr->registers;
325 model_busy *busy_ptr;
327 if (ppc_regs[ppc_RA].in_use) {
328 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
330 while (ppc_regs[ppc_RA].in_use) {
331 model_ptr->nr_stalls_data++;
332 model_new_cycle(model_ptr);
336 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
337 ppc_regs[ppc_RD].next = (model_reg *)0;
338 ppc_regs[ppc_RD].in_use = 1;
340 busy_ptr->reg = &ppc_regs[ppc_RD];
342 model_reg *reg_CR0 = &ppc_regs[0 + PPC_CR_REG];
343 reg_CR0->next = &ppc_regs[ppc_RD];
344 busy_ptr->reg = reg_CR0;
348 # Schedule an instruction that takes no integer input registers and produces an output register & possibly sets CR0
349 void::model-function::ppc_insn_int0:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rD, unsigned Rc
350 if (!WITH_MODEL_ISSUE)
354 registers *cpu_regs = cpu_registers(processor);
355 const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
356 model_reg *ppc_regs = model_ptr->registers;
357 model_busy *busy_ptr;
359 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
360 ppc_regs[ppc_RD].next = (model_reg *)0;
361 ppc_regs[ppc_RD].in_use = 1;
363 busy_ptr->reg = &ppc_regs[ppc_RD];
365 model_reg *reg_CR0 = &ppc_regs[0 + PPC_CR_REG];
366 reg_CR0->next = &ppc_regs[ppc_RD];
367 busy_ptr->reg = reg_CR0;
371 # Schedule an instruction that takes 2 integer input registers and produces an output register & updates a second register
372 void::model-function::ppc_insn_int2_update:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rD, signed_word *rA, signed_word *rB
373 if (!WITH_MODEL_ISSUE)
377 registers *cpu_regs = cpu_registers(processor);
378 const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
379 const unsigned ppc_RB = (rB - &cpu_regs->gpr[0]) + PPC_INT_REG;
380 const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
381 model_reg *ppc_regs = model_ptr->registers;
382 model_busy *busy_ptr;
384 if (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
385 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
387 while (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
388 model_ptr->nr_stalls_data++;
389 model_new_cycle(model_ptr);
393 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
394 ppc_regs[ppc_RA].next = (model_reg *)0;
395 ppc_regs[ppc_RA].in_use = 1;
397 ppc_regs[ppc_RD].next = &ppc_regs[ppc_RA];
398 ppc_regs[ppc_RD].in_use = 1;
399 busy_ptr->reg = &ppc_regs[ppc_RD];
402 # Schedule an instruction that takes 1 integer input registers and produces an output register & updates the other register
403 void::model-function::ppc_insn_int1_update:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rD, signed_word *rA
404 if (!WITH_MODEL_ISSUE)
408 registers *cpu_regs = cpu_registers(processor);
409 const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
410 const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
411 model_reg *ppc_regs = model_ptr->registers;
412 model_busy *busy_ptr;
414 if (ppc_regs[ppc_RA].in_use) {
415 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
417 while (ppc_regs[ppc_RA].in_use) {
418 model_ptr->nr_stalls_data++;
419 model_new_cycle(model_ptr);
423 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
424 ppc_regs[ppc_RA].next = (model_reg *)0;
425 ppc_regs[ppc_RA].in_use = 1;
427 ppc_regs[ppc_RD].next = &ppc_regs[ppc_RA];
428 ppc_regs[ppc_RD].in_use = 1;
429 busy_ptr->reg = &ppc_regs[ppc_RD];
432 # Schedule an instruction that takes 2 integer input registers and produces no output register
433 void::model-function::ppc_insn_int2_noout:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rA, signed_word *rB
434 if (!WITH_MODEL_ISSUE)
438 registers *cpu_regs = cpu_registers(processor);
439 const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
440 const unsigned ppc_RB = (rB - &cpu_regs->gpr[0]) + PPC_INT_REG;
441 model_reg *ppc_regs = model_ptr->registers;
443 if (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
444 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
446 while (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
447 model_ptr->nr_stalls_data++;
448 model_new_cycle(model_ptr);
452 (void) model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
455 # Schedule an instruction that takes 1 integer input registers and produces no output register
456 void::model-function::ppc_insn_int1_noout:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rA
457 if (!WITH_MODEL_ISSUE)
461 registers *cpu_regs = cpu_registers(processor);
462 const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
463 model_reg *ppc_regs = model_ptr->registers;
465 if (ppc_regs[ppc_RA].in_use) {
466 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
468 while (ppc_regs[ppc_RA].in_use) {
469 model_ptr->nr_stalls_data++;
470 model_new_cycle(model_ptr);
474 (void) model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
477 # Schedule an instruction that takes no input registers and produces no output
478 void::model-function::ppc_insn_int0_noout:itable_index index, cpu *processor, model_data *model_ptr
479 if (!WITH_MODEL_ISSUE)
483 (void) model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
486 # Schedule an instruction that takes 2 integer input registers and produces a CR output register
487 void::model-function::ppc_insn_int2_cr:itable_index index, cpu *processor, model_data *model_ptr, unsigned CRD, signed_word *rA, signed_word *rB
488 if (!WITH_MODEL_ISSUE)
492 registers *cpu_regs = cpu_registers(processor);
493 const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
494 const unsigned ppc_RB = (rB - &cpu_regs->gpr[0]) + PPC_INT_REG;
495 const unsigned ppc_CRD = CRD + PPC_CR_REG;
496 model_reg *ppc_regs = model_ptr->registers;
497 model_busy *busy_ptr;
499 if (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
500 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
502 while (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
503 model_ptr->nr_stalls_data++;
504 model_new_cycle(model_ptr);
508 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
509 ppc_regs[ppc_CRD].next = (model_reg *)0;
510 ppc_regs[ppc_CRD].in_use = 1;
511 busy_ptr->reg = &ppc_regs[ppc_CRD];
514 # Schedule an instruction that takes 1 integer input register and produces a CR output register
515 void::model-function::ppc_insn_int1_cr:itable_index index, cpu *processor, model_data *model_ptr, unsigned CRD, signed_word *rA
516 if (!WITH_MODEL_ISSUE)
520 registers *cpu_regs = cpu_registers(processor);
521 const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
522 const unsigned ppc_CRD = CRD + PPC_CR_REG;
523 model_reg *ppc_regs = model_ptr->registers;
524 model_busy *busy_ptr;
526 if (ppc_regs[ppc_RA].in_use) {
527 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
529 while (ppc_regs[ppc_RA].in_use) {
530 model_ptr->nr_stalls_data++;
531 model_new_cycle(model_ptr);
535 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
536 ppc_regs[ppc_CRD].next = (model_reg *)0;
537 ppc_regs[ppc_CRD].in_use = 1;
538 busy_ptr->reg = &ppc_regs[ppc_CRD];
541 # Schedule an MFSPR instruction that takes 1 special purpose register and produces an integer output register
542 void::model-function::ppc_insn_from_spr:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rD, unsigned nSPR
543 if (!WITH_MODEL_ISSUE)
547 registers *cpu_regs = cpu_registers(processor);
548 const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
549 const unsigned ppc_SPR = nSPR + PPC_SPR_REG;
550 model_reg *ppc_regs = model_ptr->registers;
551 model_busy *busy_ptr;
553 while (ppc_regs[ppc_SPR].in_use) {
554 model_ptr->nr_stalls_data++;
555 model_new_cycle(model_ptr);
558 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
559 ppc_regs[ppc_RD].next = (model_reg *)0;
560 ppc_regs[ppc_RD].in_use = 1;
561 busy_ptr->reg = &ppc_regs[ppc_RD];
564 # Schedule an MTSPR instruction that takes 1 integer register and produces a special purpose output register
565 void::model-function::ppc_insn_to_spr:itable_index index, cpu *processor, model_data *model_ptr, unsigned nSPR, signed_word *rS
566 if (!WITH_MODEL_ISSUE)
570 registers *cpu_regs = cpu_registers(processor);
571 const unsigned ppc_RS = (rS - &cpu_regs->gpr[0]) + PPC_INT_REG;
572 const unsigned ppc_SPR = nSPR + PPC_SPR_REG;
573 model_reg *ppc_regs = model_ptr->registers;
574 model_busy *busy_ptr;
576 while (ppc_regs[ppc_RS].in_use) {
577 model_ptr->nr_stalls_data++;
578 model_new_cycle(model_ptr);
581 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
582 ppc_regs[ppc_SPR].next = (model_reg *)0;
583 ppc_regs[ppc_SPR].in_use = 1;
584 busy_ptr->reg = &ppc_regs[ppc_SPR];
587 # Schedule a MFCR instruction that moves the CR into an integer regsiter
588 void::model-function::ppc_insn_mfcr:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rD
589 if (!WITH_MODEL_ISSUE)
593 registers *cpu_regs = cpu_registers(processor);
594 const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
595 model_reg *ppc_regs = model_ptr->registers;
596 model_busy *busy_ptr;
598 while (ppc_regs[0 + PPC_CR_REG].in_use
599 | ppc_regs[1 + PPC_CR_REG].in_use
600 | ppc_regs[2 + PPC_CR_REG].in_use
601 | ppc_regs[3 + PPC_CR_REG].in_use
602 | ppc_regs[4 + PPC_CR_REG].in_use
603 | ppc_regs[5 + PPC_CR_REG].in_use
604 | ppc_regs[6 + PPC_CR_REG].in_use
605 | ppc_regs[7 + PPC_CR_REG].in_use) {
607 model_ptr->nr_stalls_data++;
608 model_new_cycle(model_ptr);
611 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
612 ppc_regs[ppc_RD].next = (model_reg *)0;
613 ppc_regs[ppc_RD].in_use = 1;
614 busy_ptr->reg = &ppc_regs[ppc_RD];
617 # Schedule a MTCR instruction that moves an integer register into the CR
618 void::model-function::ppc_insn_mtcr:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rT
619 if (!WITH_MODEL_ISSUE)
623 registers *cpu_regs = cpu_registers(processor);
624 const unsigned ppc_RT = (rT - &cpu_regs->gpr[0]) + PPC_INT_REG;
625 model_reg *ppc_regs = model_ptr->registers;
626 model_busy *busy_ptr;
630 if (ppc_regs[ppc_RT].in_use) {
631 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
633 while (ppc_regs[ppc_RT].in_use) {
634 model_ptr->nr_stalls_data++;
635 model_new_cycle(model_ptr);
639 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
640 prev_reg = (model_reg *)0;
641 for (i = 0; i < 8; i++) {
642 ppc_regs[i + PPC_CR_REG].next = prev_reg;
643 ppc_regs[i + PPC_CR_REG].in_use = 1;
644 prev_reg = &ppc_regs[i + PPC_CR_REG];
646 busy_ptr->reg = prev_reg;
649 model_data *::model-function::model_create:cpu *processor
650 model_data *model_ptr = ZALLOC(model_data);
651 ASSERT(CURRENT_MODEL > 0 && CURRENT_MODEL < nr_models);
652 model_ptr->name = model_name[CURRENT_MODEL];
653 model_ptr->timing = model_time_mapping[CURRENT_MODEL];
654 model_ptr->processor = processor;
655 model_ptr->nr_cycles = 1;
658 void::model-function::model_init:model_data *model_ptr
660 void::model-function::model_halt:model_data *model_ptr
661 /* Let pipeline drain */
662 while (model_ptr->busy_list)
663 model_new_cycle(model_ptr);
665 model_print *::model-function::model_mon_info:model_data *model_ptr
670 head = tail = ZALLOC(model_print);
671 tail->count = model_ptr->nr_cycles;
672 tail->name = "cycle";
673 tail->suffix_plural = "s";
674 tail->suffix_singular = "";
676 if (model_ptr->nr_stalls_data) {
677 tail->next = ZALLOC(model_print);
679 tail->count = model_ptr->nr_stalls_data;
680 tail->name = "stall";
681 tail->suffix_plural = "s waiting for data";
682 tail->suffix_singular = " waiting for data";
685 if (model_ptr->nr_stalls_unit) {
686 tail->next = ZALLOC(model_print);
688 tail->count = model_ptr->nr_stalls_unit;
689 tail->name = "stall";
690 tail->suffix_plural = "s waiting for a function unit";
691 tail->suffix_singular = " waiting for a function unit";
694 if (model_ptr->nr_stalls_serialize) {
695 tail->next = ZALLOC(model_print);
697 tail->count = model_ptr->nr_stalls_serialize;
698 tail->name = "stall";
699 tail->suffix_plural = "s waiting for serialization";
700 tail->suffix_singular = " waiting for serialization";
703 if (model_ptr->nr_insns_not_handled) {
704 tail->next = ZALLOC(model_print);
706 tail->count = model_ptr->nr_insns_not_handled;
707 tail->name = "instruction";
708 tail->suffix_plural = "s that were not accounted for in timing info";
709 tail->suffix_singular = " that was not accounted for in timing info";
712 if (model_ptr->nr_branches) {
713 tail->next = ZALLOC(model_print);
715 tail->count = model_ptr->nr_branches;
716 tail->name = "branch";
717 tail->suffix_plural = "es";
718 tail->suffix_singular = "";
721 if (model_ptr->nr_branches_fallthrough) {
722 tail->next = ZALLOC(model_print);
724 tail->count = model_ptr->nr_branches_fallthrough;
725 tail->name = "conditional branch";
726 tail->suffix_plural = "es fell through";
727 tail->suffix_singular = " fell through";
730 if (model_ptr->nr_branch_predict_trues) {
731 tail->next = ZALLOC(model_print);
733 tail->count = model_ptr->nr_branch_predict_trues;
734 tail->name = "successful branch prediction";
735 tail->suffix_plural = "s";
736 tail->suffix_singular = "";
739 if (model_ptr->nr_branch_predict_falses) {
740 tail->next = ZALLOC(model_print);
742 tail->count = model_ptr->nr_branch_predict_falses;
743 tail->name = "unsuccessful branch prediction";
744 tail->suffix_plural = "s";
745 tail->suffix_singular = "";
748 for (i = PPC_UNIT_BAD; i < nr_ppc_function_units; i++) {
749 if (model_ptr->nr_units[i]) {
750 tail->next = ZALLOC(model_print);
752 tail->count = model_ptr->nr_units[i];
753 tail->name = ppc_function_unit_name[i];
754 tail->suffix_plural = "s";
755 tail->suffix_singular = "";
759 tail->next = (model_print *)0;
762 void::model-function::model_mon_info_free:model_data *model_ptr, model_print *ptr
764 model_print *next = ptr->next;
769 void::model-function::model_branches:model_data *model_ptr, int failed
770 model_ptr->nr_units[PPC_UNIT_BPU]++;
771 model_ptr->insn_handled = 1;
773 model_ptr->nr_branches_fallthrough++;
775 model_ptr->nr_branches++;
776 model_new_cycle(model_ptr); /* A branch always ends the current cycle */
778 void::model-function::model_branch_predict:model_data *model_ptr, int success
780 model_ptr->nr_branch_predict_trues++;
782 model_ptr->nr_branch_predict_falses++;
784 # The following (illegal) instruction is `known' by gen and is
785 # called when ever an illegal instruction is encountered
787 program_interrupt(processor, cia,
788 illegal_instruction_program_interrupt);
792 # The following (floating point unavailable) instruction is `known' by gen
793 # and is called when ever an a floating point instruction is to be
794 # executed but floating point is make unavailable by the MSR
795 ::internal::floating_point_unavailable
796 floating_point_unavailable_interrupt(processor, cia);
801 # Floating point support functions
804 # Convert 32bit single to 64bit double
805 unsigned64::function::DOUBLE:unsigned32 WORD
807 if (EXTRACTED32(WORD, 1, 8) > 0
808 && EXTRACTED32(WORD, 1, 8) < 255) {
809 /* normalized operand */
810 int not_word_1_1 = !EXTRACTED32(WORD, 1, 1); /*2.6.3 bug*/
811 FRT = (INSERTED64(EXTRACTED32(WORD, 0, 1), 0, 1)
812 | INSERTED64(not_word_1_1, 2, 2)
813 | INSERTED64(not_word_1_1, 3, 3)
814 | INSERTED64(not_word_1_1, 4, 4)
815 | INSERTED64(EXTRACTED32(WORD, 2, 31), 5, (63 - 29)));
817 else if (EXTRACTED32(WORD, 1, 8) == 0
818 && EXTRACTED32(WORD, 9, 31) != 0) {
819 /* denormalized operand */
820 int sign = EXTRACTED32(WORD, 0, 0);
822 unsigned64 frac = INSERTED64(EXTRACTED32(WORD, 9, 31), 1, (52 - 29));
823 /* normalize the operand */
824 while (MASKED64(frac, 0, 0) == 0) {
828 FRT = (INSERTED64(sign, 0, 0)
829 | INSERTED64(exp + 1023, 1, 11)
830 | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
832 else if (EXTRACTED32(WORD, 1, 8) == 255
833 || EXTRACTED32(WORD, 1, 31) == 0) {
834 FRT = (INSERTED64(EXTRACTED32(WORD, 0, 1), 0, 1)
835 | INSERTED64(EXTRACTED32(WORD, 1, 1), 2, 2)
836 | INSERTED64(EXTRACTED32(WORD, 1, 1), 3, 3)
837 | INSERTED64(EXTRACTED32(WORD, 1, 1), 4, 4)
838 | INSERTED64(EXTRACTED32(WORD, 2, 31), 5, (63 - 29)));
841 error("DOUBLE - unknown case\n");
846 # Convert 64bit single to 32bit double
847 unsigned32::function::SINGLE:unsigned64 FRS
849 if (EXTRACTED64(FRS, 1, 11) > 896
850 || EXTRACTED64(FRS, 1, 63) == 0) {
851 /* no denormalization required (includes Zero/Infinity/NaN) */
852 WORD = (INSERTED32(EXTRACTED64(FRS, 0, 1), 0, 1)
853 | INSERTED32(EXTRACTED64(FRS, 5, 34), 2, 31));
855 else if (874 <= EXTRACTED64(FRS, 1, 11)
856 && EXTRACTED64(FRS, 1, 11) <= 896) {
857 /* denormalization required */
858 int sign = EXTRACTED64(FRS, 0, 0);
859 int exp = EXTRACTED64(FRS, 1, 11) - 1023;
860 unsigned64 frac = (BIT64(0)
861 | INSERTED64(EXTRACTED64(FRS, 12, 63), 1, 52));
862 /* denormalize the operand */
864 frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63);
867 WORD = (INSERTED32(sign, 0, 0)
868 | INSERTED32(0x00, 1, 8)
869 | INSERTED32(EXTRACTED64(frac, 1, 23), 9, 31));
872 WORD = 0x0; /* ??? */
877 # round 64bit double to 64bit but single
878 void::function::Round_Single:cpu *processor, int sign, int *exp, unsigned64 *frac_grx
879 /* comparisons ignore u bits */
882 int lsb = EXTRACTED64(*frac_grx, 23, 23);
883 int gbit = EXTRACTED64(*frac_grx, 24, 24);
884 int rbit = EXTRACTED64(*frac_grx, 25, 25);
885 int xbit = EXTRACTED64(*frac_grx, 26, 55) != 0;
886 if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
887 if (lsb == 1 && gbit == 1) inc = 1;
888 if (lsb == 0 && gbit == 1 && rbit == 1) inc = 1;
889 if (lsb == 0 && gbit == 1 && xbit == 1) inc = 1;
891 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_pos_infinity) {
892 if (sign == 0 && gbit == 1) inc = 1;
893 if (sign == 0 && rbit == 1) inc = 1;
894 if (sign == 0 && xbit == 1) inc = 1;
896 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_neg_infinity) {
897 if (sign == 1 && gbit == 1) inc = 1;
898 if (sign == 1 && rbit == 1) inc = 1;
899 if (sign == 1 && xbit == 1) inc = 1;
901 /* work out addition in low 25 bits of out */
902 out = EXTRACTED64(*frac_grx, 0, 23) + inc;
903 *frac_grx = INSERTED64(out, 0, 23);
904 if (out & BIT64(64 - 23 - 1 - 1)) {
905 *frac_grx = (BIT64(0) |
906 INSERTED64(EXTRACTED64(*frac_grx, 0, 22), 1, 23));
909 /* frac_grx[24:52] = 0 already */
911 FPSCR_SET_FI(gbit || rbit || xbit);
915 void::function::Round_Integer:cpu *processor, int sign, unsigned64 *frac, int *frac64, int gbit, int rbit, int xbit, fpscreg round_mode
917 if (round_mode == fpscr_rn_round_to_nearest) {
918 if (*frac64 == 1 && gbit == 1) inc = 1;
919 if (*frac64 == 0 && gbit == 1 && rbit == 1) inc = 1;
920 if (*frac64 == 0 && gbit == 1 && xbit == 1) inc = 1;
922 if (round_mode == fpscr_rn_round_towards_pos_infinity) {
923 if (sign == 0 && gbit == 1) inc = 1;
924 if (sign == 0 && rbit == 1) inc = 1;
925 if (sign == 0 && xbit == 1) inc = 1;
927 if (round_mode == fpscr_rn_round_towards_neg_infinity) {
928 if (sign == 1 && gbit == 1) inc = 1;
929 if (sign == 1 && rbit == 1) inc = 1;
930 if (sign == 1 && xbit == 1) inc = 1;
932 /* frac[0:64] = frac[0:64} + inc */
933 *frac += (*frac64 && inc ? 1 : 0);
934 *frac64 = (*frac64 + inc) & 0x1;
936 FPSCR_SET_FI(gbit | rbit | xbit);
939 void::function::Round_Float:cpu *processor, int sign, int *exp, unsigned64 *frac, fpscreg round_mode
942 int lsb = EXTRACTED64(*frac, 52, 52);
943 int gbit = EXTRACTED64(*frac, 53, 53);
944 int rbit = EXTRACTED64(*frac, 54, 54);
945 int xbit = EXTRACTED64(*frac, 55, 55);
946 if (round_mode == fpscr_rn_round_to_nearest) {
947 if (lsb == 1 && gbit == 1) inc = 1;
948 if (lsb == 0 && gbit == 1 && rbit == 1) inc = 1;
949 if (lsb == 0 && gbit == 1 && xbit == 1) inc = 1;
951 if (round_mode == fpscr_rn_round_towards_pos_infinity) {
952 if (sign == 0 && gbit == 1) inc = 1;
953 if (sign == 0 && rbit == 1) inc = 1;
954 if (sign == 0 && xbit == 1) inc = 1;
956 if (round_mode == fpscr_rn_round_towards_neg_infinity) {
957 if (sign == 1 && gbit == 1) inc = 1;
958 if (sign == 1 && rbit == 1) inc = 1;
959 if (sign == 1 && xbit == 1) inc = 1;
961 /* frac//carry_out = frac + inc */
962 *frac = (*frac >> 1) + (INSERTED64(inc, 52, 52) >> 1);
963 carry_out = EXTRACTED64(*frac, 0, 0);
965 if (carry_out == 1) *exp = *exp + 1;
967 FPSCR_SET_FI(gbit | rbit | xbit);
968 FPSCR_SET_XX(FPSCR & fpscr_fi);
971 # conversion of FP to integer
972 void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64 *frt, unsigned64 frb, fpscreg round_mode, int tgt_precision
980 int sign = EXTRACTED64(frb, 0, 0);
981 if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 63) == 0)
982 goto Infinity_Operand;
983 if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 0)
985 if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 1)
987 if (EXTRACTED64(frb, 1, 11) > 1086) goto Large_Operand;
988 if (EXTRACTED64(frb, 1, 11) > 0) exp = EXTRACTED64(frb, 1, 11) - 1023;
989 if (EXTRACTED64(frb, 1, 11) == 0) exp = -1022;
990 if (EXTRACTED64(frb, 1, 11) > 0) { /* normal */
991 frac = BIT64(1) | INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
994 if (EXTRACTED64(frb, 1, 11) == 0) { /* denorm */
995 frac = INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
998 gbit = 0, rbit = 0, xbit = 0;
999 for (i = 1; i <= 63 - exp; i++) {
1003 frac64 = EXTRACTED64(frac, 63, 63);
1004 frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63);
1006 Round_Integer(processor, sign, &frac, &frac64, gbit, rbit, xbit, round_mode);
1007 if (sign == 1) { /* frac[0:64] = ~frac[0:64] + 1 */
1010 frac += (frac64 ? 1 : 0);
1011 frac64 = (frac64 + 1) & 0x1;
1013 if (tgt_precision == 32 /* can ignore frac64 in compare */
1014 && (signed64)frac > (signed64)MASK64(33+1, 63)/*2^31-1 >>1*/)
1016 if (tgt_precision == 64 /* can ignore frac64 in compare */
1017 && (signed64)frac > (signed64)MASK64(1+1, 63)/*2^63-1 >>1*/)
1019 if (tgt_precision == 32 /* can ignore frac64 in compare */
1020 && (signed64)frac < (signed64)MASK64(0, 32+1)/*-2^31 >>1*/)
1022 if (tgt_precision == 64 /* can ignore frac64 in compare */
1023 && (signed64)frac < (signed64)MASK64(0, 0+1)/*-2^63 >>1*/)
1025 FPSCR_SET_XX(FPSCR & fpscr_fi);
1026 if (tgt_precision == 32)
1027 *frt = MASKED64(*frt, 0, 31) | (EXTRACTED64(frac, 33, 63) << 1) | frac64;
1028 if (tgt_precision == 64)
1029 *frt = (EXTRACTED64(frac, 1, 63) << 1) | frac64;
1030 /*FPSCR[fprf] = undefined */
1036 FPSCR_OR_VX(fpscr_vxcvi);
1037 if ((FPSCR & fpscr_ve) == 0) {
1038 if (tgt_precision == 32) {
1039 if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7FFFFFFF;
1040 if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1043 if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/
1044 if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
1046 /* FPSCR[FPRF] = undefined */
1053 FPSCR_OR_VX(fpscr_vxsnan | fpscr_vxcvi);
1054 if ((FPSCR & fpscr_ve) == 0) {
1055 if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1056 if (tgt_precision == 64) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
1057 /* FPSCR[fprf] = undefined */
1064 FPSCR_OR_VX(fpscr_vxcvi);
1065 if ((FPSCR & fpscr_ve) == 0) {
1066 if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1067 if (tgt_precision == 64) *frt = BIT64(0);/*0x8000_0000_0000_0000*/
1068 /* FPSCR[fprf] = undefined */
1075 FPSCR_OR_VX(fpscr_vxcvi);
1076 if ((FPSCR & fpscr_ve) == 0) {
1077 if (tgt_precision == 32) {
1078 if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7fffffff;
1079 if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1082 if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/
1083 if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
1085 /* FPSCR[fprf] = undefined */
1091 # extract out raw fields of a FP number
1092 int::function::sign:unsigned64 FRS
1093 return (MASKED64(FRS, 0, 0)
1096 int::function::biased_exp:unsigned64 frs, int single
1098 return EXTRACTED64(frs, 1, 8);
1100 return EXTRACTED64(frs, 1, 11);
1101 unsigned64::function::fraction:unsigned64 frs, int single
1103 return EXTRACTED64(frs, 9, 31);
1105 return EXTRACTED64(frs, 12, 63);
1107 # a number?, each of the below return +1 or -1 (based on sign bit)
1109 int::function::is_nor:unsigned64 frs, int single
1110 int exp = biased_exp(frs, single);
1112 && exp <= (single ? 254 : 2046));
1113 int::function::is_zero:unsigned64 FRS
1114 return (MASKED64(FRS, 1, 63) == 0
1117 int::function::is_den:unsigned64 frs, int single
1118 int exp = biased_exp(frs, single);
1119 unsigned64 frac = fraction(frs, single);
1120 return (exp == 0 && frac != 0
1123 int::function::is_inf:unsigned64 frs, int single
1124 int exp = biased_exp(frs, single);
1125 int frac = fraction(frs, single);
1126 return (exp == (single ? 255 : 2047) && frac == 0
1129 int::function::is_NaN:unsigned64 frs, int single
1130 int exp = biased_exp(frs, single);
1131 int frac = fraction(frs, single);
1132 return (exp == (single ? 255 : 2047) && frac != 0
1135 int::function::is_SNaN:unsigned64 frs, int single
1136 return (is_NaN(frs, single)
1137 && !(frs & (single ? MASK64(9, 9) : MASK64(12, 12)))
1140 int::function::is_QNaN:unsigned64 frs, int single
1141 return (is_NaN(frs, single) && !is_SNaN(frs, single));
1142 int::function::is_less_than:unsigned64 *fra, unsigned64 *frb
1143 return *(double*)fra < *(double*)frb;
1144 int::function::is_greater_than:unsigned64 *fra, unsigned64 *frb
1145 return *(double*)fra > *(double*)frb;
1146 int::function::is_equan_to:unsigned64 *fra, unsigned64 *frb
1147 return *(double*)fra == *(double*)frb;
1150 # which quiet nan should become the result
1151 unsigned64::function::select_qnan:unsigned64 fra, unsigned64 frb, unsigned64 frc, int instruction_is_frsp, int generate_qnan, int single
1153 if (is_NaN(fra, single))
1155 else if (is_NaN(frb, single))
1156 if (instruction_is_frsp)
1157 frt = MASKED64(frb, 0, 34);
1160 else if (is_NaN(frc, single))
1162 else if (generate_qnan)
1163 frt = MASK64(1, 12); /* 0x7FF8_0000_0000_0000 */
1165 error("select_qnan - default reached\n");
1169 # detect invalid operation
1170 int::function::is_invalid_operation:cpu *processor, unsigned_word cia, unsigned64 fra, unsigned64 frb, fpscreg check, int single, int negate
1172 if ((check & fpscr_vxsnan)
1173 && (is_SNaN(fra, single) || is_SNaN(frb, single))) {
1174 FPSCR_OR_VX(fpscr_vxsnan);
1177 if ((check & fpscr_vxisi)
1178 && (is_inf(fra, single) && is_inf(frb, single))
1179 && ((negate && sign(fra) != sign(frb))
1180 || (!negate && sign(fra) == sign(frb)))) {
1181 /*FIXME: don't handle inf-inf VS inf+-inf */
1182 FPSCR_OR_VX(fpscr_vxisi);
1185 if ((check & fpscr_vxidi)
1186 && (is_inf(fra, single) && is_inf(frb, single))) {
1187 FPSCR_OR_VX(fpscr_vxidi);
1190 if ((check & fpscr_vxzdz)
1191 && (is_zero(fra) && is_zero(frb))) {
1192 FPSCR_OR_VX(fpscr_vxzdz);
1195 if ((check & fpscr_vximz)
1196 && (is_zero(fra) && is_inf(frb, single))) {
1197 FPSCR_OR_VX(fpscr_vximz);
1200 if ((check & fpscr_vxvc)
1201 && (is_NaN(fra, single) || is_NaN(frb, single))) {
1202 FPSCR_OR_VX(fpscr_vxvc);
1205 if ((check & fpscr_vxsoft)) {
1206 FPSCR_OR_VX(fpscr_vxsoft);
1209 if ((check & fpscr_vxsqrt)
1211 FPSCR_OR_VX(fpscr_vxsqrt);
1214 /* if ((check && fpscr_vxcvi) {
1215 && (is_inf(fra, single) || is_NaN(fra, single) || is_large(fra, single)))
1216 FPSCR_OR_VX(fpscr_vxcvi);
1226 # handle case of invalid operation
1227 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
1228 if (FPSCR & fpscr_ve) {
1229 /* invalid operation exception enabled */
1233 /* fpscr_FPRF unchanged */
1236 /* invalid operation exception disabled */
1237 if (instruction_is_convert_to_64bit) {
1240 else if (instruction_is_convert_to_32bit) {
1243 else { /* arrith, frsp */
1244 *frt = select_qnan(fra, frb, frc,
1245 instruction_is_frsp, 0/*generate*/, single);
1248 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
1256 # I.2.4.1 Branch Instructions
1258 0.18,6.LI,30.AA,31.LK:I:t::Branch
1259 *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1260 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1261 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1262 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1263 if (AA) NIA = IEA(EXTS(LI_0b00));
1264 else NIA = IEA(CIA + EXTS(LI_0b00));
1265 if (LK) LR = (spreg)CIA+4;
1266 model_branches(cpu_model(processor), 1);
1268 0.16,6.BO,11.BI,16.BD,30.AA,31.LK:B:t::Branch Conditional
1269 *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1270 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1271 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1272 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1273 int M, ctr_ok, cond_ok, succeed;
1275 model_wait_for_cr(cpu_model(processor), BIT32_BI);
1276 if (is_64bit_implementation && is_64bit_mode) M = 0;
1278 if (!BO{2}) CTR = CTR - 1;
1279 ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != (BO{3}));
1280 cond_ok = BO{0} || ((CR{BI}) == (BO{1}));
1281 if (ctr_ok && cond_ok) {
1282 if (AA) NIA = IEA(EXTS(BD_0b00));
1283 else NIA = IEA(CIA + EXTS(BD_0b00));
1288 if (LK) LR = (spreg)IEA(CIA + 4);
1289 model_branches(cpu_model(processor), succeed);
1292 if (BO{4}) { /* branch prediction bit set, reverse sense of test */
1293 reverse = EXTS(BD_0b00) < 0;
1294 } else { /* branch prediction bit not set */
1295 reverse = EXTS(BD_0b00) >= 0;
1297 model_branch_predict(cpu_model(processor), reverse ? !succeed : succeed);
1300 0.19,6.BO,11.BI,16./,21.16,31.LK:XL:t::Branch Conditional to Link Register
1301 *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1302 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1303 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1304 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1305 int M, ctr_ok, cond_ok, succeed;
1306 if (is_64bit_implementation && is_64bit_mode) M = 0;
1309 model_wait_for_cr(cpu_model(processor), BIT32_BI);
1310 if (!BO{2}) CTR = CTR - 1;
1311 ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != BO{3});
1312 cond_ok = BO{0} || (CR{BI} == BO{1});
1313 if (ctr_ok && cond_ok) {
1319 if (LK) LR = (spreg)IEA(CIA + 4);
1320 model_branches(cpu_model(processor), succeed);
1322 model_branch_predict(cpu_model(processor), BO{4} ? !succeed : succeed);
1324 0.19,6.BO,11.BI,16./,21.528,31.LK:XL:t::Branch Conditional to Count Register
1325 *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1326 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1327 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1328 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1329 int cond_ok, succeed;
1331 model_wait_for_cr(cpu_model(processor), BIT32_BI);
1332 cond_ok = BO{0} || (CR{BI} == BO{1});
1334 NIA = IEA(CTR_0b00);
1339 if (LK) LR = (spreg)IEA(CIA + 4);
1340 model_branches(cpu_model(processor), succeed);
1342 model_branch_predict(cpu_model(processor), BO{4} ? !succeed : succeed);
1345 # I.2.4.2 System Call Instruction
1347 0.17,6./,11./,16./,30.1,31./:SC:t::System Call
1348 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1349 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
1350 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
1351 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1352 model_serialize(my_index, cpu_model(processor));
1353 system_call_interrupt(processor, cia);
1356 # I.2.4.3 Condition Register Logical Instructions
1358 0.19,6.BT,11.BA,16.BB,21.257,31./:XL::crand:Condition Register AND
1359 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1360 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1361 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1362 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1363 BLIT32(CR, BT, CR{BA} && CR{BB});
1365 0.19,6.BT,11.BA,16.BB,21.449,31./:XL::cror:Condition Register OR
1366 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1367 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1368 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1369 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1370 BLIT32(CR, BT, CR{BA} || CR{BB});
1372 0.19,6.BT,11.BA,16.BB,21.193,31./:XL::crxor:Condition Register XOR
1373 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1374 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1375 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1376 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1377 BLIT32(CR, BT, CR{BA} != CR{BB});
1379 0.19,6.BT,11.BA,16.BB,21.225,31./:XL::crnand:Condition Register NAND
1380 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1381 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1382 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1383 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1384 BLIT32(CR, BT, !(CR{BA} && CR{BB}));
1386 0.19,6.BT,11.BA,16.BB,21.33,31./:XL::crnor:Condition Register NOR
1387 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1388 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1389 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1390 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1391 BLIT32(CR, BT, !(CR{BA} || CR{BB}));
1393 0.19,6.BT,11.BA,16.BB,21.289,31./:XL::creqv:Condition Register Equivalent
1394 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1395 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1396 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1397 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1398 BLIT32(CR, BT, CR{BA} == CR{BB});
1400 0.19,6.BT,11.BA,16.BB,21.129,31./:XL::crandc:Condition Register AND with Complement
1401 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1402 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1403 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1404 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1405 BLIT32(CR, BT, CR{BA} && !CR{BB});
1407 0.19,6.BT,11.BA,16.BB,21.417,31./:XL::crorc:Condition Register OR with Complement
1408 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1409 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1410 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1411 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1412 BLIT32(CR, BT, CR{BA} || !CR{BB});
1415 # I.2.4.4 Condition Register Field Instruction
1417 0.19,6.BF,9./,11.BFA,14./,16./,21.0,31./:XL:::Move Condition Register Field
1418 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1419 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1420 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1421 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1422 MBLIT32(CR, 4*BF, 4*BF+3, EXTRACTED32(CR, 4*BFA, 4*BFA+3));
1426 # I.3.3.2 Fixed-Point Load Instructions
1429 0.34,6.RT,11.RA,16.D:D:::Load Byte and Zero
1430 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1431 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1432 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1433 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1439 *rT = MEM(unsigned, EA, 1);
1441 ppc_insn_int0(my_index, processor, cpu_model(processor), rT, 0/*Rc*/);
1443 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
1446 0.31,6.RT,11.RA,16.RB,21.87,31./:X:::Load Byte and Zero Indexed
1447 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1448 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1449 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1450 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1456 *rT = MEM(unsigned, EA, 1);
1458 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rB, 0/*Rc*/);
1460 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, 0/*Rc*/);
1462 0.35,6.RT,11.RA,16.D:D:::Load Byte and Zero with Update
1463 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1464 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1465 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1466 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1468 if (RA == 0 || RA == RT)
1469 program_interrupt(processor, cia,
1470 illegal_instruction_program_interrupt);
1472 *rT = MEM(unsigned, EA, 1);
1474 ppc_insn_int1_update(my_index, processor, cpu_model(processor), rT, rA);
1476 0.31,6.RT,11.RA,16.RB,21.119,31./:X:::Load Byte and Zero with Update Indexed
1477 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1478 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1479 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1480 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1482 if (RA == 0 || RA == RT)
1483 program_interrupt(processor, cia,
1484 illegal_instruction_program_interrupt);
1486 *rT = MEM(unsigned, EA, 1);
1488 ppc_insn_int2_update(my_index, processor, cpu_model(processor), rT, rA, rB);
1490 0.40,6.RT,11.RA,16.D:D:::Load Halfword and Zero
1491 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1492 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1493 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1494 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1500 *rT = MEM(unsigned, EA, 2);
1502 ppc_insn_int0(my_index, processor, cpu_model(processor), rT, 0/*Rc*/);
1504 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
1506 0.31,6.RT,11.RA,16.RB,21.279,31./:X:::Load Halfword and Zero Indexed
1507 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1508 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1509 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1510 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1516 *rT = MEM(unsigned, EA, 2);
1518 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rB, 0/*Rc*/);
1520 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, 0/*Rc*/);
1522 0.41,6.RT,11.RA,16.D:D:::Load Halfword and Zero with Update
1523 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1524 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1525 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1526 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1528 if (RA == 0 || RA == RT)
1529 program_interrupt(processor, cia,
1530 illegal_instruction_program_interrupt);
1532 *rT = MEM(unsigned, EA, 2);
1534 ppc_insn_int1_update(my_index, processor, cpu_model(processor), rT, rA);
1536 0.31,6.RT,11.RA,16.RB,21.311,31./:X:::Load Halfword and Zero with Update Indexed
1537 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1538 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1539 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1540 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1542 if (RA == 0 || RA == RT)
1543 program_interrupt(processor, cia,
1544 illegal_instruction_program_interrupt);
1546 *rT = MEM(unsigned, EA, 2);
1548 ppc_insn_int2_update(my_index, processor, cpu_model(processor), rT, rA, rB);
1550 0.42,6.RT,11.RA,16.D:D:::Load Halfword Algebraic
1551 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1552 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1553 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1554 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1560 *rT = MEM(signed, EA, 2);
1562 ppc_insn_int0(my_index, processor, cpu_model(processor), rT, 0/*Rc*/);
1564 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
1566 0.31,6.RT,11.RA,16.RB,21.343,31./:X:::Load Halfword Algebraic Indexed
1567 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1568 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1569 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1570 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1576 *rT = MEM(signed, EA, 2);
1578 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rB, 0/*Rc*/);
1580 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, 0/*Rc*/);
1582 0.43,6.RT,11.RA,16.D:D:::Load Halfword Algebraic with Update
1583 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1584 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1585 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1586 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1588 if (RA == 0 || RA == RT)
1589 program_interrupt(processor, cia,
1590 illegal_instruction_program_interrupt);
1592 *rT = MEM(signed, EA, 2);
1593 ppc_insn_int1_update(my_index, processor, cpu_model(processor), rT, rA);
1595 0.31,6.RT,11.RA,16.RB,21.375,31./:X:::Load Halfword Algebraic with Update Indexed
1596 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1597 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1598 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1599 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1601 if (RA == 0 || RA == RT)
1602 program_interrupt(processor, cia,
1603 illegal_instruction_program_interrupt);
1605 *rT = MEM(signed, EA, 2);
1607 ppc_insn_int2_update(my_index, processor, cpu_model(processor), rT, rA, rB);
1609 0.32,6.RT,11.RA,16.D:D:::Load Word and Zero
1610 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1611 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1612 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1613 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1619 *rT = MEM(unsigned, EA, 4);
1621 ppc_insn_int0(my_index, processor, cpu_model(processor), rT, 0/*Rc*/);
1623 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
1625 0.31,6.RT,11.RA,16.RB,21.23,31./:X:::Load Word and Zero Indexed
1626 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1627 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1628 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1629 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1635 *rT = MEM(unsigned, EA, 4);
1637 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rB, 0/*Rc*/);
1639 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, 0/*Rc*/);
1641 0.33,6.RT,11.RA,16.D:D:::Load Word and Zero with Update
1642 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1643 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1644 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1645 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1647 if (RA == 0 || RA == RT)
1648 program_interrupt(processor, cia,
1649 illegal_instruction_program_interrupt);
1651 *rT = MEM(unsigned, EA, 4);
1653 ppc_insn_int1_update(my_index, processor, cpu_model(processor), rT, rA);
1655 0.31,6.RT,11.RA,16.RB,21.55,31./:X:::Load Word and Zero with Update Indexed
1656 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1657 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1658 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1659 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1661 if (RA == 0 || RA == RT)
1662 program_interrupt(processor, cia,
1663 illegal_instruction_program_interrupt);
1665 *rT = MEM(unsigned, EA, 4);
1667 ppc_insn_int2_update(my_index, processor, cpu_model(processor), rT, rA, rB);
1669 0.58,6.RT,11.RA,16.DS,30.2:DS:64::Load Word Algebraic
1672 # if (RA == 0) b = 0;
1674 # EA = b + EXTS(DS_0b00);
1675 # *rT = MEM(signed, EA, 4);
1677 0.31,6.RT,11.RA,16.RB,21.341,31./:X:64::Load Word Algebraic Indexed
1680 # if (RA == 0) b = 0;
1683 # *rT = MEM(signed, EA, 4);
1685 0.31,6.RT,11.RA,16.RB,21.373,31./:X:64::Load Word Algebraic with Update Indexed
1687 # if (RA == 0 || RA == RT)
1688 # program_interrupt(processor, cia
1689 # illegal_instruction_program_interrupt);
1691 # *rT = MEM(signed, EA, 4);
1694 0.58,6.RT,11.RA,16.DS,30.0:DS:64::Load Doubleword
1697 # if (RA == 0) b = 0;
1699 # EA = b + EXTS(DS_0b00);
1700 # *rT = MEM(unsigned, EA, 8);
1702 0.31,6.RT,11.RA,16.RB,21.21,31./:X:64::Load Doubleword Indexed
1705 # if (RA == 0) b = 0;
1708 # *rT = MEM(unsigned, EA, 8);
1710 0.58,6.RT,11.RA,16.DS,30.1:DS:64::Load Doubleword with Update
1712 # if (RA == 0 || RA == RT)
1713 # program_interrupt(processor, cia
1714 # illegal_instruction_program_interrupt);
1715 # EA = *rA + EXTS(DS_0b00);
1716 # *rT = MEM(unsigned, EA, 8);
1719 0.31,6.RT,11.RA,16.RB,21.53,31./:DS:64::Load Doubleword with Update Indexed
1721 # if (RA == 0 || RA == RT)
1722 # program_interrupt(processor, cia
1723 # illegal_instruction_program_interrupt);
1725 # *rT = MEM(unsigned, EA, 8);
1731 # I.3.3.3 Fixed-Point Store Instructions
1734 0.38,6.RS,11.RA,16.D:D:::Store Byte
1735 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1736 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1737 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1738 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1746 ppc_insn_int0_noout(my_index, processor, cpu_model(processor));
1748 ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rA);
1750 0.31,6.RS,11.RA,16.RB,21.215,31./:X:::Store Byte Indexed
1751 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1752 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1753 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1754 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1762 ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
1764 ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
1766 0.39,6.RS,11.RA,16.D:D:::Store Byte with Update
1767 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1768 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1769 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1770 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1773 program_interrupt(processor, cia,
1774 illegal_instruction_program_interrupt);
1778 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rA, 0/*Rc*/);
1780 0.31,6.RS,11.RA,16.RB,21.247,31./:X:::Store Byte with Update Indexed
1781 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1782 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1783 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1784 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1787 program_interrupt(processor, cia,
1788 illegal_instruction_program_interrupt);
1792 ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rA, rB, 0/*Rc*/);
1794 0.44,6.RS,11.RA,16.D:D:::Store Half Word
1795 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1796 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1797 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1798 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1806 ppc_insn_int0_noout(my_index, processor, cpu_model(processor));
1808 ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rA);
1810 0.31,6.RS,11.RA,16.RB,21.407,31./:X:::Store Half Word Indexed
1811 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1812 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1813 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1814 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1822 ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
1824 ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
1826 0.45,6.RS,11.RA,16.D:D:::Store Half Word with Update
1827 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1828 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1829 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1830 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1833 program_interrupt(processor, cia,
1834 illegal_instruction_program_interrupt);
1838 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rA, 0/*Rc*/);
1840 0.31,6.RS,11.RA,16.RB,21.439,31./:X:::Store Half Word with Update Indexed
1841 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1842 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1843 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1844 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1847 program_interrupt(processor, cia,
1848 illegal_instruction_program_interrupt);
1852 ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rA, rB, 0/*Rc*/);
1854 0.36,6.RS,11.RA,16.D:D:::Store Word
1855 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1856 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1857 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1858 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1866 ppc_insn_int0_noout(my_index, processor, cpu_model(processor));
1868 ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rA);
1870 0.31,6.RS,11.RA,16.RB,21.151,31./:X:::Store Word Indexed
1871 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1872 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1873 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1874 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1882 ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
1884 ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
1886 0.37,6.RS,11.RA,16.D:D:::Store Word with Update
1887 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1888 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1889 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1890 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1893 program_interrupt(processor, cia,
1894 illegal_instruction_program_interrupt);
1898 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rA, 0/*Rc*/);
1900 0.31,6.RS,11.RA,16.RB,21.183,31./:X:::Store Word with Update Indexed
1901 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1902 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1903 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1904 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1907 program_interrupt(processor, cia,
1908 illegal_instruction_program_interrupt);
1912 ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rA, rB, 0/*Rc*/);
1914 0.62,6.RS,11.RA,16.DS,30.0:DS:64::Store Doubleword
1917 # if (RA == 0) b = 0;
1919 # EA = b + EXTS(DS_0b00);
1920 # STORE(EA, 8, *rS);
1921 0.31,6.RS,11.RA,16.RB,21.149,31./:X:64::Store Doubleword Indexed
1924 # if (RA == 0) b = 0;
1927 # STORE(EA, 8, *rS);
1928 0.62,6.RS,11.RA,16.DS,30.1:DS:64::Store Doubleword with Update
1931 # program_interrupt(processor, cia
1932 # illegal_instruction_program_interrupt);
1933 # EA = *rA + EXTS(DS_0b00);
1934 # STORE(EA, 8, *rS);
1936 0.31,6.RS,11.RA,16.RB,21.181,31./:X:64::Store Doubleword with Update Indexed
1939 # program_interrupt(processor, cia
1940 # illegal_instruction_program_interrupt);
1942 # STORE(EA, 8, *rS);
1947 # I.3.3.4 Fixed-Point Load and Store with Byte Reversal Instructions
1950 0.31,6.RT,11.RA,16.RB,21.790,31./:X:::Load Halfword Byte-Reverse Indexed
1951 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 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, 3, 0
1960 *rT = SWAP_2(MEM(unsigned, EA, 2));
1962 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rB, 0/*Rc*/);
1964 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, 0/*Rc*/);
1966 0.31,6.RT,11.RA,16.RB,21.534,31./:X:::Load Word Byte-Reverse Indexed
1967 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 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, 3, 0
1976 *rT = SWAP_4(MEM(unsigned, EA, 4));
1978 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rB, 0/*Rc*/);
1980 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, 0/*Rc*/);
1982 0.31,6.RS,11.RA,16.RB,21.918,31./:X:::Store Half Word Byte-Reversed Indexed
1983 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1984 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1985 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1986 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1992 STORE(EA, 2, SWAP_2(*rS));
1994 ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
1996 ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
1998 0.31,6.RS,11.RA,16.RB,21.662,31./:X:::Store Word Byte-Reversed Indexed
1999 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2000 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2001 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2002 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2008 STORE(EA, 4, SWAP_4(*rS));
2010 ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
2012 ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
2016 # I.3.3.5 Fixed-Point Load and Store Multiple Instrctions
2019 0.46,6.RT,11.RA,16.D:D:be::Load Multiple Word
2021 0.47,6.RS,11.RA,16.D:D:be::Store Multiple Word
2025 # I.3.3.6 Fixed-Point Move Assist Instructions
2028 0.31,6.RT,11.RA,16.NB,21.597,31./:X:be::Load String Word Immediate
2030 0.31,6.RT,11.RA,16.RB,21.533,31./:X:be::Load String Word Indexed
2032 0.31,6.RS,11.RA,16.NB,21.725,31./:X:be::Store String Word Immedate
2034 0.31,6.RS,11.RA,16.RB,21.661,31./:X:be::Store String Word Indexed
2038 # I.3.3.7 Storage Synchronization Instructions
2040 # HACK: Rather than monitor addresses looking for a reason
2041 # to cancel a reservation. This code instead keeps
2042 # a copy of the data read from memory. Before performing
2043 # a store, the memory area is checked to see if it has
2045 0.31,6.RT,11.RA,16.RB,21.20,31./:X:::Load Word And Reserve Indexed
2046 *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2047 *603: PPC_UNIT_LSU, PPC_UNIT_IU, 1, 2, 0
2048 *603e:PPC_UNIT_LSU, PPC_UNIT_IU, 1, 2, 0
2049 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2056 RESERVE_ADDR = real_addr(EA, 1/*is-read?*/);
2057 RESERVE_DATA = MEM(unsigned, EA, 4);
2060 0.31,6.RT,11.RA,16.RB,21.84,31./:X:64::Load Doubleword And Reserve Indexed
2067 RESERVE_ADDR = real_addr(EA, 1/*is-read?*/);
2068 RESERVE_DATA = MEM(unsigned, EA, 8);
2071 0.31,6.RS,11.RA,16.RB,21.150,31.1:X:::Store Word Conditional Indexed
2072 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2073 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 8, 8, 0
2074 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 8, 8, 0
2075 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 3, 0
2082 if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/)
2083 && /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 4)) {
2085 CR_SET_XER_SO(0, cr_i_zero);
2088 /* ment to randomly to store, we never do! */
2089 CR_SET_XER_SO(0, 0);
2094 CR_SET_XER_SO(0, 0);
2096 0.31,6.RS,11.RA,16.RB,21.214,31.1:X:64::Store Doubleword Conditional Indexed
2103 if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/)
2104 && /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 8)) {
2106 CR_SET_XER_SO(0, cr_i_zero);
2109 /* ment to randomly to store, we never do */
2110 CR_SET_XER_SO(0, 0);
2115 CR_SET_XER_SO(0, 0);
2118 0.31,6./,11./,16./,21.598,31./:X::sync:Synchronize
2119 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2120 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
2121 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
2122 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
2127 # I.3.3.9 Fixed-Point Arithmetic Instructions
2130 0.14,6.RT,11.RA,16.SI:D:T::Add Immediate
2131 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2132 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2133 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2134 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2137 ppc_insn_int0(my_index, processor, cpu_model(processor), rT, 0/*Rc*/);
2140 *rT = *rA + EXTS(SI);
2141 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
2144 0.15,6.RT,11.RA,16.SI:D:::Add Immediate Shifted
2145 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2146 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2147 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2148 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2150 *rT = EXTS(SI) << 16;
2151 ppc_insn_int0(my_index, processor, cpu_model(processor), rT, 0/*Rc*/);
2154 *rT = *rA + (EXTS(SI) << 16);
2155 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
2158 0.31,6.RT,11.RA,16.RB,21.OE,22.266,31.Rc:XO:::Add
2159 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2160 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2161 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2162 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2165 ALU_END(*rT, 0/*CA*/, OE, Rc);
2166 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2168 0.31,6.RT,11.RA,16.RB,21.OE,22.40,31.Rc:XO:::Subtract From
2169 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2170 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2171 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2172 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2177 ALU_END(*rT, 0/*CA*/, OE, Rc);
2178 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2180 0.12,6.RT,11.RA,16.SI:D:::Add Immediate Carrying
2181 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2182 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2183 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2184 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2187 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
2188 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
2190 0.13,6.RT,11.RA,16.SI:D:::Add Immediate Carrying and Record
2191 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2192 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2193 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2194 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2197 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 1/*Rc*/);
2198 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 1/*Rc*/);
2200 0.8,6.RT,11.RA,16.SI:D:::Subtract From Immediate Carrying
2201 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2202 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2203 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2204 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2209 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
2210 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
2212 0.31,6.RT,11.RA,16.RB,21.OE,22.10,31.Rc:XO:::Add Carrying
2213 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2214 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2215 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2216 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2219 ALU_END(*rT, 1/*CA*/, OE, Rc);
2220 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2222 0.31,6.RT,11.RA,16.RB,21.OE,22.8,31.Rc:XO:::Subtract From Carrying
2223 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2224 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2225 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2226 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2227 /* RT <- ~RA + RB + 1 === RT <- RB - RA */
2232 ALU_END(*rT, 1/*CA*/, OE, Rc);
2233 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2235 0.31,6.RT,11.RA,16.RB,21.OE,22.138,31.Rc:XO:::Add Extended
2236 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2237 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2238 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2239 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2243 ALU_END(*rT, 1/*CA*/, OE, Rc);
2244 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2246 0.31,6.RT,11.RA,16.RB,21.OE,22.136,31.Rc:XO:::Subtract From Extended
2247 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2248 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2249 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2250 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2255 ALU_END(*rT, 1/*CA*/, OE, Rc);
2256 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2258 0.31,6.RT,11.RA,16./,21.OE,22.234,31.Rc:XO:::Add to Minus One Extended
2259 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2260 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2261 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2262 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2266 # ALU_END(*rT, 1/*CA*/, OE, Rc);
2268 0.31,6.RT,11.RA,16./,21.OE,22.232,31.Rc:XO:::Subtract From Minus One Extended
2269 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2270 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2271 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2272 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2277 # ALU_END(*rT, 1/*CA*/, OE, Rc);
2279 0.31,6.RT,11.RA,16./,21.OE,22.202,31.Rc:XO::addze:Add to Zero Extended
2280 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2281 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2282 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2283 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2286 ALU_END(*rT, 1/*CA*/, OE, Rc);
2287 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, Rc);
2289 0.31,6.RT,11.RA,16./,21.OE,22.200,31.Rc:XO:::Subtract from Zero Extended
2290 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2291 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2292 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2293 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2297 ALU_END(*rT, 1/*CA*/, OE, Rc);
2298 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, Rc);
2300 0.31,6.RT,11.RA,16./,21.OE,22.104,31.Rc:XO:::Negate
2301 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2302 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2303 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2304 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2308 ALU_END(*rT,0/*CA*/,OE,Rc);
2309 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, Rc);
2311 0.7,6.RT,11.RA,16.SI:D::mulli:Multiply Low Immediate
2312 *601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2313 *603: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
2314 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
2315 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
2316 signed_word prod = *rA * EXTS(SI);
2318 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
2320 0.31,6.RT,11.RA,16.RB,21.OE,22.233,31.Rc:D:64::Multiply Low Doubleword
2322 0.31,6.RT,11.RA,16.RB,21.OE,22.235,31.Rc:XO::mullw:Multiply Low Word
2323 *601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2324 *603: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2325 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2326 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0
2327 signed64 a = (signed32)(*rA);
2328 signed64 b = (signed32)(*rB);
2329 signed64 prod = a * b;
2330 signed_word t = prod;
2332 if (t != prod && OE)
2333 XER |= (xer_overflow | xer_summary_overflow);
2334 CR0_COMPARE(t, 0, Rc);
2335 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2337 0.31,6.RT,11.RA,16.RB,21./,22.73,31.Rc:XO:64::Multiply High Doubleword
2339 0.31,6.RT,11.RA,16.RB,21./,22.75,31.Rc:XO::mulhw:Multiply High Word
2340 *601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2341 *603: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2342 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2343 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0
2344 signed64 a = (signed32)(*rA);
2345 signed64 b = (signed32)(*rB);
2346 signed64 prod = a * b;
2347 signed_word t = EXTRACTED64(prod, 0, 31);
2349 CR0_COMPARE(t, 0, Rc);
2350 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2352 0.31,6.RT,11.RA,16.RB,21./,22.9,31.Rc:XO:64::Multiply High Doubleword Unsigned
2354 0.31,6.RT,11.RA,16.RB,21./,22.11,31.Rc:XO::milhwu:Multiply High Word Unsigned
2355 *601: PPC_UNIT_IU, PPC_UNIT_IU, 10, 10, 0
2356 *603: PPC_UNIT_IU, PPC_UNIT_IU, 6, 6, 0
2357 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 6, 6, 0
2358 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0
2359 unsigned64 a = (unsigned32)(*rA);
2360 unsigned64 b = (unsigned32)(*rB);
2361 unsigned64 prod = a * b;
2362 signed_word t = EXTRACTED64(prod, 0, 31);
2364 CR0_COMPARE(t, 0, Rc);
2365 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2367 0.31,6.RT,11.RA,16.RB,21.OE,22.489,31.Rc:XO:64::Divide Doubleword
2369 0.31,6.RT,11.RA,16.RB,21.OE,22.491,31.Rc:XO::divw:Divide Word
2370 *601: PPC_UNIT_IU, PPC_UNIT_IU, 36, 36, 0
2371 *603: PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2372 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2373 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 20, 20, 0
2374 signed64 dividend = (signed32)(*rA);
2375 signed64 divisor = (signed32)(*rB);
2376 if (divisor == 0 /* nb 0x8000..0 is sign extended */
2377 || (dividend == 0x80000000 && divisor == -1)) {
2379 XER |= (xer_overflow | xer_summary_overflow);
2380 CR0_COMPARE(0, 0, Rc);
2383 signed64 quotent = dividend / divisor;
2385 CR0_COMPARE((signed_word)quotent, 0, Rc);
2387 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2389 0.31,6.RT,11.RA,16.RB,21.OE,22.457,31.Rc:XO:64::Divide Doubleword Unsigned
2391 0.31,6.RT,11.RA,16.RB,21.OE,22.459,31.Rc:XO::divwu:Divide Word Unsigned
2392 *601: PPC_UNIT_IU, PPC_UNIT_IU, 36, 36, 0
2393 *603: PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2394 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2395 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 20, 20, 0
2396 unsigned64 dividend = (unsigned32)(*rA);
2397 unsigned64 divisor = (unsigned32)(*rB);
2400 XER |= (xer_overflow | xer_summary_overflow);
2401 CR0_COMPARE(0, 0, Rc);
2404 unsigned64 quotent = dividend / divisor;
2406 CR0_COMPARE((signed_word)quotent, 0, Rc);
2408 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2412 # I.3.3.10 Fixed-Point Compare Instructions
2415 0.11,6.BF,9./,10.L,11.RA,16.SI:D:::Compare Immediate
2416 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2417 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2418 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2419 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2420 if (!is_64bit_mode && L)
2421 program_interrupt(processor, cia,
2422 illegal_instruction_program_interrupt);
2425 signed_word b = EXTS(SI);
2430 CR_COMPARE(BF, a, b);
2432 ppc_insn_int1_cr(my_index, processor, cpu_model(processor), BF, rA);
2434 0.31,6.BF,9./,10.L,11.RA,16.RB,21.0,31./:X:::Compare
2435 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2436 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2437 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2438 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2439 if (!is_64bit_mode && L)
2440 program_interrupt(processor, cia,
2441 illegal_instruction_program_interrupt);
2453 CR_COMPARE(BF, a, b);
2455 ppc_insn_int2_cr(my_index, processor, cpu_model(processor), BF, rA, rB);
2457 0.10,6.BF,9./,10.L,11.RA,16.UI:D:::Compare Logical Immediate
2458 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2459 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2460 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2461 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2462 if (!is_64bit_mode && L)
2463 program_interrupt(processor, cia,
2464 illegal_instruction_program_interrupt);
2467 unsigned_word b = UI;
2469 a = MASKED(*rA, 32, 63);
2472 CR_COMPARE(BF, a, b);
2474 ppc_insn_int1_cr(my_index, processor, cpu_model(processor), BF, rA);
2476 0.31,6.BF,9./,10.L,11.RA,16.RB,21.32,31./:X:::Compare Logical
2477 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2478 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2479 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2480 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2481 if (!is_64bit_mode && L)
2482 program_interrupt(processor, cia,
2483 illegal_instruction_program_interrupt);
2488 a = MASKED(*rA, 32, 63);
2489 b = MASKED(*rB, 32, 63);
2495 CR_COMPARE(BF, a, b);
2497 ppc_insn_int2_cr(my_index, processor, cpu_model(processor), BF, rA, rB);
2501 # I.3.3.11 Fixed-Point Trap Instructions
2504 0.2,6.TO,11.RA,16.SI:D:64::Trap Doubleword Immediate
2506 program_interrupt(processor, cia,
2507 illegal_instruction_program_interrupt);
2509 signed_word a = *rA;
2510 signed_word b = EXTS(SI);
2511 if ((a < b && TO{0})
2513 || (a == b && TO{2})
2514 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2515 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2517 program_interrupt(processor, cia,
2518 trap_program_interrupt);
2521 0.3,6.TO,11.RA,16.SI:D:::Trap Word Immediate
2522 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2523 *603: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2524 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2525 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2526 signed_word a = EXTENDED(*rA);
2527 signed_word b = EXTS(SI);
2528 if ((a < b && TO{0})
2530 || (a == b && TO{2})
2531 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2532 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2534 program_interrupt(processor, cia,
2535 trap_program_interrupt);
2537 0.31,6.TO,11.RA,16.RB,21.68,31./:X:64::Trap Doubleword
2539 program_interrupt(processor, cia,
2540 illegal_instruction_program_interrupt);
2542 signed_word a = *rA;
2543 signed_word b = *rB;
2544 if ((a < b && TO{0})
2546 || (a == b && TO{2})
2547 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2548 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2550 program_interrupt(processor, cia,
2551 trap_program_interrupt);
2554 0.31,6.TO,11.RA,16.RB,21.4,31./:X:::Trap Word
2555 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2556 *603: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2557 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2558 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2559 signed_word a = EXTENDED(*rA);
2560 signed_word b = EXTENDED(*rB);
2561 if (TO == 12 && rA == rB) {
2562 ITRACE(trace_breakpoint, ("breakpoint\n"));
2563 cpu_halt(processor, cia, was_trap, 0);
2565 else if ((a < b && TO{0})
2567 || (a == b && TO{2})
2568 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2569 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2571 program_interrupt(processor, cia,
2572 trap_program_interrupt);
2575 # I.3.3.12 Fixed-Point Logical Instructions
2578 0.28,6.RS,11.RA,16.UI:D:::AND Immediate
2579 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2580 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2581 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2582 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2584 CR0_COMPARE(*rA, 0, 1/*Rc*/);
2585 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, 1/*Rc*/);
2587 0.29,6.RS,11.RA,16.UI:D:::AND Immediate Shifted
2588 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2589 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2590 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2591 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2592 *rA = *rS & (UI << 16);
2593 CR0_COMPARE(*rA, 0, 1/*Rc*/);
2594 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, 1/*Rc*/);
2596 0.24,6.RS,11.RA,16.UI:D:::OR Immediate
2597 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2598 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2599 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2600 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2602 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, 0);
2604 0.25,6.RS,11.RA,16.UI:D:::OR Immediate Shifted
2605 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2606 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2607 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2608 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2609 *rA = *rS | (UI << 16);
2610 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, 0);
2612 0.26,6.RS,11.RA,16.UI:D:::XOR Immediate
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
2618 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, 0);
2620 0.27,6.RS,11.RA,16.UI:D:::XOR Immediate Shifted
2621 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2622 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2623 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2624 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2625 *rA = *rS ^ (UI << 16);
2626 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, 0);
2628 0.31,6.RS,11.RA,16.RB,21.28,31.Rc:X:::AND
2629 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2630 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2631 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2632 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2634 CR0_COMPARE(*rA, 0, Rc);
2635 ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
2637 0.31,6.RS,11.RA,16.RB,21.444,31.Rc:X:::OR
2638 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2639 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2640 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2641 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2643 CR0_COMPARE(*rA, 0, Rc);
2644 ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
2646 0.31,6.RS,11.RA,16.RB,21.316,31.Rc:X:::XOR
2647 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2648 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2649 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2650 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2652 CR0_COMPARE(*rA, 0, Rc);
2653 ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
2655 0.31,6.RS,11.RA,16.RB,21.476,31.Rc:X:::NAND
2656 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2657 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2658 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2659 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2661 CR0_COMPARE(*rA, 0, Rc);
2662 ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
2664 0.31,6.RS,11.RA,16.RB,21.124,31.Rc:X:::NOR
2665 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2666 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2667 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2668 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2670 CR0_COMPARE(*rA, 0, Rc);
2671 ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
2673 0.31,6.RS,11.RA,16.RB,21.284,31.Rc:X:::Equivalent
2674 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2675 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2676 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2677 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2678 # *rA = ~(*rS ^ *rB); /* A === B */
2679 # CR0_COMPARE(*rA, 0, Rc);
2681 0.31,6.RS,11.RA,16.RB,21.60,31.Rc:X:::AND with Complement
2682 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2683 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2684 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2685 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2687 CR0_COMPARE(*rA, 0, Rc);
2688 ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
2690 0.31,6.RS,11.RA,16.RB,21.412,31.Rc:X:::OR with Complement
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
2696 CR0_COMPARE(*rA, 0, Rc);
2697 ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
2699 0.31,6.RS,11.RA,16./,21.954,31.Rc:X::extsb:Extend Sign Byte
2700 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2701 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2702 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2703 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2704 *rA = (signed_word)(signed8)*rS;
2705 CR0_COMPARE(*rA, 0, Rc);
2706 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
2708 0.31,6.RS,11.RA,16./,21.922,31.Rc:X::extsh:Extend Sign Half Word
2709 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2710 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2711 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2712 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2713 *rA = (signed_word)(signed16)*rS;
2714 CR0_COMPARE(*rA, 0, Rc);
2715 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
2717 0.31,6.RS,11.RA,16./,21.986,31.Rc:X:64::Extend Sign Word
2718 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2719 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2720 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2721 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2722 # *rA = (signed_word)(signed32)*rS;
2723 # CR0_COMPARE(*rA, 0, Rc);
2725 0.31,6.RS,11.RA,16./,21.58,31.Rc:X:64::Count Leading Zeros Doubleword
2727 # unsigned64 mask = BIT64(0);
2728 # unsigned64 source = *rS;
2729 # while (!(source & mask) && mask != 0) {
2734 # CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */
2736 0.31,6.RS,11.RA,16./,21.26,31.Rc:X:::Count Leading Zeros Word
2737 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2738 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2739 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2740 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2742 unsigned32 mask = BIT32(0);
2743 unsigned32 source = *rS;
2744 while (!(source & mask) && mask != 0) {
2749 CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */
2753 # I.3.3.13 Fixed-Point Rotate and Shift Instructions
2756 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
2757 # long n = (sh_5 << 4) | sh_0_4;
2758 # unsigned_word r = ROTL64(*rS, n);
2759 # long b = (mb_5 << 4) | mb_0_4;
2760 # unsigned_word m = MASK(b, 63);
2761 # signed_word result = r & m;
2763 # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
2765 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
2766 # long n = (sh_5 << 4) | sh_0_4;
2767 # unsigned_word r = ROTL64(*rS, n);
2768 # long e = (me_5 << 4) | me_0_4;
2769 # unsigned_word m = MASK(0, e);
2770 # signed_word result = r & m;
2772 # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
2774 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
2775 # long n = (sh_5 << 4) | sh_0_4;
2776 # unsigned_word r = ROTL64(*rS, n);
2777 # long b = (mb_5 << 4) | mb_0_4;
2778 # unsigned_word m = MASK(0, (64-n));
2779 # signed_word result = r & m;
2781 # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
2783 0.21,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M:::Rotate Left Word Immediate then AND with Mask
2784 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2785 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2786 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2787 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2790 unsigned32 r = ROTL32(s, n);
2791 unsigned32 m = MASK(MB+32, ME+32);
2792 signed_word result = r & m;
2794 CR0_COMPARE(result, 0, Rc);
2796 ("n=%d, s=0x%x, r=0x%x, m=0x%x, result=0x%x, cr=0x%x\n",
2797 n, s, r, m, result, CR));
2798 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
2800 0.30,6.RS,11.RA,16.RB,21.mb,27.8,31.Rc:MDS:64::Rotate Left Doubleword then Clear Left
2801 # long n = MASKED(*rB, 58, 63);
2802 # unsigned_word r = ROTL64(*rS, n);
2803 # long b = (mb_5 << 4) | mb_0_4;
2804 # unsigned_word m = MASK(b, 63);
2805 # signed_word result = r & m;
2807 # CR0_COMPARE(result, 0, Rc);
2809 0.30,6.RS,11.RA,16.RB,21.me,27.9,31.Rc:MDS:64::Rotate Left Doubleword then Clear Right
2810 # long n = MASKED(*rB, 58, 63);
2811 # unsigned_word r = ROTL64(*rS, n);
2812 # long e = (me_5 << 4) | me_0_4;
2813 # unsigned_word m = MASK(0, e);
2814 # signed_word result = r & m;
2816 # CR0_COMPARE(result, 0, Rc);
2818 0.23,6.RS,11.RA,16.RB,21.MB,26.ME,31.Rc:M:::Rotate Left Word then AND with Mask
2819 # long n = MASKED(*rB, 59, 63);
2820 # unsigned32 r = ROTL32(*rS, n);
2821 # unsigned32 m = MASK(MB+32, ME+32);
2822 # signed_word result = r & m;
2824 # CR0_COMPARE(result, 0, Rc);
2826 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
2827 # long n = (sh_5 << 4) | sh_0_4;
2828 # unsigned_word r = ROTL64(*rS, n);
2829 # long b = (mb_5 << 4) | mb_0_4;
2830 # unsigned_word m = MASK(b, (64-n));
2831 # signed_word result = (r & m) | (*rA & ~m)
2833 # CR0_COMPARE(result, 0, Rc);
2835 0.20,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M::rlwimi:Rotate Left Word Immediate then Mask Insert
2836 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2837 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2838 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2839 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2841 unsigned32 r = ROTL32(*rS, n);
2842 unsigned32 m = MASK(MB+32, ME+32);
2843 signed_word result = (r & m) | (*rA & ~m);
2845 ITRACE(trace_alu, (": n=%d *rS=0x%x r=0x%x m=0x%x result=0x%x\n",
2846 n, *rS, r, m, result));
2847 CR0_COMPARE(result, 0, Rc);
2848 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
2851 0.31,6.RS,11.RA,16.RB,21.27,31.Rc:X:64::Shift Left Doubleword
2853 0.31,6.RS,11.RA,16.RB,21.24,31.Rc:X:::Shift Left Word
2854 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2855 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2856 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2857 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2858 int n = MASKED(*rB, 59, 63);
2859 unsigned32 source = *rS;
2860 signed_word shifted;
2862 shifted = (source << n);
2866 CR0_COMPARE(shifted, 0, Rc);
2868 ("n=%d, source=0x%x, shifted=0x%x\n",
2869 n, source, shifted));
2870 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
2872 0.31,6.RS,11.RA,16.RB,21.539,31.Rc:X:64::Shift Right Doubleword
2874 0.31,6.RS,11.RA,16.RB,21.536,31.Rc:X:::Shift Right Word
2875 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2876 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2877 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2878 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2879 int n = MASKED(*rB, 59, 63);
2880 unsigned32 source = *rS;
2881 signed_word shifted;
2883 shifted = (source >> n);
2887 CR0_COMPARE(shifted, 0, Rc);
2889 ("n=%d, source=0x%x, shifted=0x%x\n",
2890 n, source, shifted));
2891 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
2893 0.31,6.RS,11.RA,16.sh_0_4,21.413,30.sh_5,31.Rc:XS:64::Shift Right Algebraic Doubleword Immediate
2895 0.31,6.RS,11.RA,16.SH,21.824,31.Rc:X:::Shift Right Algebraic Word Immediate
2896 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2897 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2898 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2899 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2901 signed_word r = ROTL32(*rS, /*64*/32-n);
2902 signed_word m = MASK(n+32, 63);
2903 int S = MASKED(*rS, 32, 32);
2904 signed_word shifted = (r & m) | (S ? ~m : 0);
2906 if (S && ((r & ~m) & MASK(32, 63)) != 0)
2910 CR0_COMPARE(shifted, 0, Rc);
2911 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
2913 0.31,6.RS,11.RA,16.RB,21.794,31.Rc:X:64::Shift Right Algebraic Doubleword
2915 0.31,6.RS,11.RA,16.RB,21.792,31.Rc:X:::Shift Right Algebraic Word
2916 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2917 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2918 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2919 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2920 int n = MASKED(*rB, 58, 63);
2921 int shift = (n >= 31 ? 31 : n);
2922 signed32 source = (signed32)*rS; /* signed to keep sign bit */
2923 signed32 shifted = source >> shift;
2924 unsigned32 mask = ((unsigned32)-1) >> (31-shift);
2925 *rA = (signed_word)shifted; /* if 64bit will sign extend */
2926 if (source < 0 && (source & mask))
2930 CR0_COMPARE(shifted, 0, Rc);
2931 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
2934 # I.3.3.14 Move to/from System Register Instructions
2937 0.31,6.RS,11.spr,21.467,31./:XFX::mtspr %SPR, %RS:Move to Special Purpose Register
2938 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2939 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
2940 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
2941 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
2942 int n = (spr{5:9} << 5) | spr{0:4};
2943 if (spr{0} && IS_PROBLEM_STATE(processor))
2944 program_interrupt(processor, cia,
2945 privileged_instruction_program_interrupt);
2946 else if (!spr_is_valid(n)
2947 || spr_is_readonly(n))
2948 program_interrupt(processor, cia,
2949 illegal_instruction_program_interrupt);
2951 spreg new_val = (spr_length(n) == 64
2953 : MASKED(*rS, 32, 63));
2954 /* HACK - time base registers need to be updated immediatly */
2955 if (WITH_TIME_BASE) {
2959 cpu_set_time_base(processor,
2960 (MASKED64(cpu_get_time_base(processor), 32, 63)
2961 | INSERTED64(new_val, 0, 31)));
2964 cpu_set_time_base(processor,
2965 (MASKED64(cpu_get_time_base(processor), 0, 31)
2966 | INSERTED64(new_val, 32, 63)));
2969 cpu_set_decrementer(processor, new_val);
2980 ppc_insn_to_spr(my_index, processor, cpu_model(processor), n, rS);
2982 0.31,6.RT,11.spr,21.339,31./:XFX::mfspr %RT, %SPR:Move from Special Purpose Register
2983 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2984 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
2985 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
2986 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
2987 int n = (spr{5:9} << 5) | spr{0:4};
2988 if (spr{0} && IS_PROBLEM_STATE(processor))
2989 program_interrupt(processor, cia,
2990 privileged_instruction_program_interrupt);
2991 else if (!spr_is_valid(n))
2992 program_interrupt(processor, cia,
2993 illegal_instruction_program_interrupt);
2995 /* HACK - some SPR's need to get their value extracted specially */
2998 ppc_insn_from_spr(my_index, processor, cpu_model(processor), rT, n);
3000 # FIXME: 604 uses SCIU{1,2} if only one bit is being set
3001 0.31,6.RS,11./,12.FXM,20./,21.144,31./:XFX::mtfcr:Move to Condition Register Fields
3002 *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
3003 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3004 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3005 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
3010 unsigned_word mask = 0;
3012 for (f = 0; f < 8; f++) {
3013 if (FXM & (0x80 >> f))
3014 mask |= (0xf << 4*(7-f));
3016 CR = (MASKED(*rS, 32, 63) & mask) | (CR & ~mask);
3018 ppc_insn_mtcr(my_index, processor, cpu_model(processor), rS);
3020 0.31,6.BF,9./,11./,16./,21.512,31./:X:::Move to Condition Register from XER
3022 0.31,6.RT,11./,16./,21.19,31./:X:::Move From Condition Register
3023 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3024 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3025 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3026 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
3027 *rT = (unsigned32)CR;
3028 ppc_insn_mfcr(my_index, processor, cpu_model(processor), rT);
3031 # I.4.6.2 Floating-Point Load Instructions
3034 0.48,6.FRT,11.RA,16.D:D:f:lfs:Load Floating-Point Single
3035 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3036 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3037 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3038 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3044 *frT = DOUBLE(MEM(unsigned, EA, 4));
3046 0.31,6.FRT,11.RA,16.RB,21.535,31./:X:f::Load Floating-Point Single Indexed
3047 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3048 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3049 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3050 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3056 *frT = DOUBLE(MEM(unsigned, EA, 4));
3058 0.49,6.FRT,11.RA,16.D:D:f::Load Floating-Point Single with Update
3059 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3060 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3061 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3062 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3065 program_interrupt(processor, cia,
3066 illegal_instruction_program_interrupt);
3068 *frT = DOUBLE(MEM(unsigned, EA, 4));
3071 0.31,6.FRT,11.RA,16.RB,21.576,31./:X:f::Load Floating-Point Single with Update Indexed
3072 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3073 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3074 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3075 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3078 program_interrupt(processor, cia,
3079 illegal_instruction_program_interrupt);
3081 *frT = DOUBLE(MEM(unsigned, EA, 4));
3084 0.50,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double
3085 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3086 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3087 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3088 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3094 *frT = MEM(unsigned, EA, 8);
3096 0.31,6.FRT,11.RA,16.RB,21.599,31./:X:f::Load Floating-Point Double Indexed
3097 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3098 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3099 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3100 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3106 *frT = MEM(unsigned, EA, 8);
3108 0.51,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double with Update
3109 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3110 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3111 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3112 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3115 program_interrupt(processor, cia,
3116 illegal_instruction_program_interrupt);
3118 *frT = MEM(unsigned, EA, 8);
3121 0.31,6.FRT,11.RA,16.RB,21.631,31./:X:f::Load Floating-Point Double with Update Indexed
3122 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3123 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3124 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3125 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3128 program_interrupt(processor, cia,
3129 illegal_instruction_program_interrupt);
3131 *frT = MEM(unsigned, EA, 8);
3136 # I.4.6.3 Floating-Point Store Instructions
3139 0.52,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single
3140 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3141 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3142 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3143 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3149 STORE(EA, 4, SINGLE(*frS));
3151 0.31,6.FRS,11.RA,16.RB,21.663,31./:X:f::Store Floating-Point Single Indexed
3152 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3153 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3154 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3155 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3161 STORE(EA, 4, SINGLE(*frS));
3163 0.53,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single with Update
3164 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3165 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3166 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3167 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3170 program_interrupt(processor, cia,
3171 illegal_instruction_program_interrupt);
3173 STORE(EA, 4, SINGLE(*frS));
3176 0.31,6.FRS,11.RA,16.RB,21.695,31./:X:f::Store Floating-Point Single with Update Indexed
3177 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3178 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3179 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3180 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3183 program_interrupt(processor, cia,
3184 illegal_instruction_program_interrupt);
3186 STORE(EA, 4, SINGLE(*frS));
3189 0.54,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double
3190 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3191 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3192 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3193 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3201 0.31,6.FRS,11.RA,16.RB,21.727,31./:X:f::Store Floating-Point Double Indexed
3202 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3203 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3204 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3205 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3213 0.55,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double with Update
3214 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3215 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3216 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3217 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3220 program_interrupt(processor, cia,
3221 illegal_instruction_program_interrupt);
3226 0.31,6.FRS,11.RA,16.RB,21.759,31./:X:f::Store Floating-Point Double with Update Indexed
3227 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3228 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3229 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3230 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3233 program_interrupt(processor, cia,
3234 illegal_instruction_program_interrupt);
3241 # I.4.6.4 Floating-Point Move Instructions
3244 0.63,6.FRT,11./,16.FRB,21.72,31.Rc:X:f::Floating Move Register
3245 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3246 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3247 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3248 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3252 0.63,6.FRT,11./,16.FRB,21.40,31.Rc:X:f::Floating Negate
3253 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3254 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3255 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3256 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3257 *frT = *frB ^ BIT64(0);
3260 0.63,6.FRT,11./,16.FRB,21.264,31.Rc:X:f::Floating Absolute Value
3261 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3262 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3263 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3264 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3265 *frT = *frB & ~BIT64(0);
3268 0.63,6.FRT,11./,16.FRB,21.136,31.Rc:X:f::Floating Negative Absolute Value
3269 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3270 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3271 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3272 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3273 *frT = *frB | BIT64(0);
3279 # I.4.6.5 Floating-Point Arithmetic Instructions
3282 0.63,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadd:Floating Add
3283 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3284 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3285 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3286 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3288 if (is_invalid_operation(processor, cia,
3290 fpscr_vxsnan | fpscr_vxisi,
3293 invalid_arithemetic_operation(processor, cia,
3295 0, /*instruction_is_frsp*/
3296 0, /*instruction_is_convert_to_64bit*/
3297 0, /*instruction_is_convert_to_32bit*/
3298 0); /*single-precision*/
3302 double s = *(double*)frA + *(double*)frB;
3307 0.59,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadds:Floating Add Single
3308 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3309 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3310 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3311 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3313 if (is_invalid_operation(processor, cia,
3315 fpscr_vxsnan | fpscr_vxisi,
3318 invalid_arithemetic_operation(processor, cia,
3320 0, /*instruction_is_frsp*/
3321 0, /*instruction_is_convert_to_64bit*/
3322 0, /*instruction_is_convert_to_32bit*/
3323 1); /*single-precision*/
3327 float s = *(double*)frA + *(double*)frB;
3332 0.63,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsub:Floating Subtract
3333 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3334 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3335 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3336 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3338 if (is_invalid_operation(processor, cia,
3340 fpscr_vxsnan | fpscr_vxisi,
3343 invalid_arithemetic_operation(processor, cia,
3345 0, /*instruction_is_frsp*/
3346 0, /*instruction_is_convert_to_64bit*/
3347 0, /*instruction_is_convert_to_32bit*/
3348 0); /*single-precision*/
3352 double s = *(double*)frA - *(double*)frB;
3357 0.59,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsubs:Floating Subtract Single
3358 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3359 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3360 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3361 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3363 if (is_invalid_operation(processor, cia,
3365 fpscr_vxsnan | fpscr_vxisi,
3368 invalid_arithemetic_operation(processor, cia,
3370 0, /*instruction_is_frsp*/
3371 0, /*instruction_is_convert_to_64bit*/
3372 0, /*instruction_is_convert_to_32bit*/
3373 1); /*single-precision*/
3377 float s = *(double*)frA - *(double*)frB;
3382 0.63,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmul:Floating Multiply
3383 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3384 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3385 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3386 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3388 if (is_invalid_operation(processor, cia,
3390 fpscr_vxsnan | fpscr_vximz,
3393 invalid_arithemetic_operation(processor, cia,
3395 0, /*instruction_is_frsp*/
3396 0, /*instruction_is_convert_to_64bit*/
3397 0, /*instruction_is_convert_to_32bit*/
3398 0); /*single-precision*/
3402 double s = *(double*)frA * *(double*)frC;
3407 0.59,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmuls:Floating Multiply Single
3408 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3409 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3410 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3411 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3413 if (is_invalid_operation(processor, cia,
3415 fpscr_vxsnan | fpscr_vximz,
3418 invalid_arithemetic_operation(processor, cia,
3420 0, /*instruction_is_frsp*/
3421 0, /*instruction_is_convert_to_64bit*/
3422 0, /*instruction_is_convert_to_32bit*/
3423 1); /*single-precision*/
3427 float s = *(double*)frA * *(double*)frC;
3432 0.63,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdiv:Floating Divide
3433 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 31, 31, 0
3434 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 33, 33, 0
3435 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 33, 33, 0
3436 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 32, 32, 0
3438 if (is_invalid_operation(processor, cia,
3440 fpscr_vxsnan | fpscr_vxzdz,
3443 invalid_arithemetic_operation(processor, cia,
3445 0, /*instruction_is_frsp*/
3446 0, /*instruction_is_convert_to_64bit*/
3447 0, /*instruction_is_convert_to_32bit*/
3448 0); /*single-precision*/
3452 double s = *(double*)frA / *(double*)frB;
3457 0.59,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdivs:Floating Divide Single
3458 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 17, 17, 0
3459 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0
3460 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0
3461 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0
3463 if (is_invalid_operation(processor, cia,
3465 fpscr_vxsnan | fpscr_vxzdz,
3468 invalid_arithemetic_operation(processor, cia,
3470 0, /*instruction_is_frsp*/
3471 0, /*instruction_is_convert_to_64bit*/
3472 0, /*instruction_is_convert_to_32bit*/
3473 1); /*single-precision*/
3477 float s = *(double*)frA / *(double*)frB;
3482 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f:fmadd:Floating Multiply-Add
3483 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3484 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3485 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3486 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3488 double product; /*HACK! - incorrectly loosing precision ... */
3489 /* compute the multiply */
3490 if (is_invalid_operation(processor, cia,
3492 fpscr_vxsnan | fpscr_vximz,
3495 invalid_arithemetic_operation(processor, cia,
3496 (unsigned64*)&product, *frA, 0, *frC,
3497 0, /*instruction_is_frsp*/
3498 0, /*instruction_is_convert_to_64bit*/
3499 0, /*instruction_is_convert_to_32bit*/
3500 0); /*single-precision*/
3504 product = *(double*)frA * *(double*)frC;
3506 /* compute the add */
3507 if (is_invalid_operation(processor, cia,
3509 fpscr_vxsnan | fpscr_vxisi,
3512 invalid_arithemetic_operation(processor, cia,
3513 frT, product, *frB, 0,
3514 0, /*instruction_is_frsp*/
3515 0, /*instruction_is_convert_to_64bit*/
3516 0, /*instruction_is_convert_to_32bit*/
3517 0); /*single-precision*/
3521 double s = product + *(double*)frB;
3526 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f::Floating Multiply-Add Single
3527 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3528 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3529 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3530 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3532 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract
3533 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3534 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3535 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3536 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3538 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract Single
3539 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3540 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3541 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3542 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3544 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add
3545 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3546 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3547 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3548 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3550 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add Single
3551 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3552 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3553 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3554 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3556 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract
3557 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3558 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3559 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3560 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3562 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract Single
3563 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3564 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3565 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3566 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3570 # I.4.6.6 Floating-Point Rounding and Conversion Instructions
3573 0.63,6.FRT,11./,16.FRB,21.12,31.Rc:X:f::Floating Round to Single-Precision
3574 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3575 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3576 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3577 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3580 unsigned64 frac_grx;
3581 /* split off cases for what to do */
3582 if (EXTRACTED64(*frB, 1, 11) < 897
3583 && EXTRACTED64(*frB, 1, 63) > 0) {
3584 if ((FPSCR & fpscr_ue) == 0) goto Disabled_Exponent_Underflow;
3585 if ((FPSCR & fpscr_ue) != 0) goto Enabled_Exponent_Underflow;
3587 if (EXTRACTED64(*frB, 1, 11) > 1150
3588 && EXTRACTED64(*frB, 1, 11) < 2047) {
3589 if ((FPSCR & fpscr_oe) == 0) goto Disabled_Exponent_Overflow;
3590 if ((FPSCR & fpscr_oe) != 0) goto Enabled_Exponent_Overflow;
3592 if (EXTRACTED64(*frB, 1, 11) > 896
3593 && EXTRACTED64(*frB, 1, 11) < 1151) goto Normal_Operand;
3594 if (EXTRACTED64(*frB, 1, 63) == 0) goto Zero_Operand;
3595 if (EXTRACTED64(*frB, 1, 11) == 2047) {
3596 if (EXTRACTED64(*frB, 12, 63) == 0) goto Infinity_Operand;
3597 if (EXTRACTED64(*frB, 12, 12) == 1) goto QNaN_Operand;
3598 if (EXTRACTED64(*frB, 12, 12) == 0
3599 && EXTRACTED64(*frB, 13, 63) > 0) goto SNaN_Operand;
3602 Disabled_Exponent_Underflow:
3603 sign = EXTRACTED64(*frB, 0, 0);
3604 if (EXTRACTED64(*frB, 1, 11) == 0) {
3606 frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
3608 if (EXTRACTED64(*frB, 1, 11) > 0) {
3609 exp = EXTRACTED64(*frB, 1, 11) - 1023;
3610 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
3612 Denormalize_Operand:
3613 /* G|R|X == zero from above */
3614 while (exp < -126) {
3616 frac_grx = (INSERTED64(EXTRACTED64(frac_grx, 0, 54), 1, 55)
3617 | MASKED64(frac_grx, 55, 55));
3619 FPSCR_SET_UX(EXTRACTED64(frac_grx, 24, 55) > 0);
3620 Round_Single(processor, sign, &exp, &frac_grx);
3621 FPSCR_SET_XX(FPSCR & fpscr_fi);
3622 if (EXTRACTED64(frac_grx, 0, 52) == 0) {
3623 *frT = INSERTED64(sign, 0, 0);
3624 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
3625 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
3627 if (EXTRACTED64(frac_grx, 0, 52) > 0) {
3628 if (EXTRACTED64(frac_grx, 0, 0) == 1) {
3629 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
3630 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
3632 if (EXTRACTED64(frac_grx, 0, 0) == 0) {
3633 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_denormalized_number);
3634 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_denormalized_number);
3636 /*Normalize_Operand:*/
3637 while (EXTRACTED64(frac_grx, 0, 0) == 0) {
3639 frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1, 52), 0, 51);
3641 *frT = (INSERTED64(sign, 0, 0)
3642 | INSERTED64(exp + 1023, 1, 11)
3643 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
3646 Enabled_Exponent_Underflow:
3648 sign = EXTRACTED64(*frB, 0, 0);
3649 if (EXTRACTED64(*frB, 1, 11) == 0) {
3651 frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
3653 if (EXTRACTED64(*frB, 1, 11) > 0) {
3654 exp = EXTRACTED64(*frB, 1, 11) - 1023;
3655 frac_grx = (BIT64(0) |
3656 INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52));
3658 /*Normalize_Operand:*/
3659 while (EXTRACTED64(frac_grx, 0, 0) == 0) {
3661 frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1, 52), 0, 51);
3663 Round_Single(processor, sign, &exp, &frac_grx);
3664 FPSCR_SET_XX(FPSCR & fpscr_fi);
3666 *frT = (INSERTED64(sign, 0, 0)
3667 | INSERTED64(exp + 1023, 1, 11)
3668 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
3669 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
3670 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
3672 Disabled_Exponent_Overflow:
3674 if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
3675 if (EXTRACTED64(*frB, 0, 0) == 0) {
3676 *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
3677 FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
3679 if (EXTRACTED64(*frB, 0, 0) == 1) {
3680 *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
3681 FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
3684 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_zero) {
3685 if (EXTRACTED64(*frB, 0, 0) == 0) {
3686 *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
3687 FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
3689 if (EXTRACTED64(*frB, 0, 0) == 1) {
3690 *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
3691 FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
3694 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_pos_infinity) {
3695 if (EXTRACTED64(*frB, 0, 0) == 0) {
3696 *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
3697 FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
3699 if (EXTRACTED64(*frB, 0, 0) == 1) {
3700 *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
3701 FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
3704 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_neg_infinity) {
3705 if (EXTRACTED64(*frB, 0, 0) == 0) {
3706 *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
3707 FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
3709 if (EXTRACTED64(*frB, 0, 0) == 1) {
3710 *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
3711 FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
3714 /* FPSCR[FR] <- undefined */
3718 Enabled_Exponent_Overflow:
3719 sign = EXTRACTED64(*frB, 0, 0);
3720 exp = EXTRACTED64(*frB, 1, 11) - 1023;
3721 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
3722 Round_Single(processor, sign, &exp, &frac_grx);
3723 FPSCR_SET_XX(FPSCR & fpscr_fi);
3727 *frT = (INSERTED64(sign, 0, 0)
3728 | INSERTED64(exp + 1023, 1, 11)
3729 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
3730 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
3731 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
3735 if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
3736 if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
3742 if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
3743 if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
3748 *frT = INSERTED64(EXTRACTED64(*frB, 0, 34), 0, 34);
3749 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
3754 FPSCR_OR_VX(fpscr_vxsnan);
3755 if ((FPSCR & fpscr_ve) == 0) {
3756 *frT = (MASKED64(*frB, 0, 11)
3758 | MASKED64(*frB, 13, 34));
3759 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
3765 sign = EXTRACTED64(*frB, 0, 0);
3766 exp = EXTRACTED64(*frB, 1, 11) - 1023;
3767 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
3768 Round_Single(processor, sign, &exp, &frac_grx);
3769 FPSCR_SET_XX(FPSCR & fpscr_fi);
3770 if (exp > 127 && (FPSCR & fpscr_oe) == 0) goto Disabled_Exponent_Overflow;
3771 if (exp > 127 && (FPSCR & fpscr_oe) != 0) goto Enabled_Overflow;
3772 *frT = (INSERTED64(sign, 0, 0)
3773 | INSERTED64(exp + 1023, 1, 11)
3774 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
3775 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
3776 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
3780 0.63,6.FRT,11./,16.FRB,21.814,31.Rc:X:64,f::Floating Convert To Integer Doubleword
3782 0.63,6.FRT,11./,16.FRB,21.815,31.Rc:X:64,f::Floating Convert To Integer Doubleword with round towards Zero
3784 0.63,6.FRT,11./,16.FRB,21.14,31.Rc:X:f::Floating Convert To Integer Word
3786 0.63,6.FRT,11./,16.FRB,21.15,31.Rc:X:f:fctiwz:Floating Convert To Integer Word with round towards Zero
3787 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3788 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3789 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3790 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3792 convert_to_integer(processor, cia,
3794 fpscr_rn_round_towards_zero, 32);
3797 0.63,6.FRT,11./,16.FRB,21.846,31.Rc:X:64,f::Floating Convert from Integer Doubleword
3798 int sign = EXTRACTED64(*frB, 0, 0);
3800 unsigned64 frac = *frB;
3801 if (frac == 0) goto Zero_Operand;
3802 if (sign == 1) frac = ~frac + 1;
3803 while (EXTRACTED64(frac, 0, 0) == 0) {
3804 /*??? do the loop 0 times if (FRB) = max negative integer */
3805 frac = INSERTED64(EXTRACTED64(frac, 1, 63), 0, 62);
3808 Round_Float(processor, sign, &exp, &frac, FPSCR & fpscr_rn);
3809 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
3810 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
3811 *frT = (INSERTED64(sign, 0, 0)
3812 | INSERTED64(exp + 1023, 1, 11)
3813 | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
3819 FPSCR_SET_FPRF(fpscr_rf_pos_zero);
3826 # I.4.6.7 Floating-Point Compare Instructions
3829 0.63,6.BF,9./,11.FRA,16.FRB,21.0,31./:X:f:fcmpu:Floating Compare Unordered
3830 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3831 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3832 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3833 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3836 if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
3837 c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
3838 else if (is_less_than(frA, frB))
3839 c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
3840 else if (is_greater_than(frA, frB))
3841 c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
3843 c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
3845 CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
3846 if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0))
3847 FPSCR_OR_VX(fpscr_vxsnan);
3850 0.63,6.BF,9./,11.FRA,16.FRB,21.32,31./:X:f:fcmpo:Floating Compare Ordered
3851 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3852 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3853 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3854 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3857 if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
3858 c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
3859 else if (is_less_than(frA, frB))
3860 c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
3861 else if (is_greater_than(frA, frB))
3862 c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
3864 c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
3866 CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
3867 if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0)) {
3868 FPSCR_OR_VX(fpscr_vxsnan);
3869 if ((FPSCR & fpscr_ve) == 0)
3870 FPSCR_OR_VX(fpscr_vxvc);
3872 else if (is_QNaN(*frA, 0) || is_QNaN(*frB, 0)) {
3873 FPSCR_OR_VX(fpscr_vxvc);
3879 # I.4.6.8 Floating-Point Status and Control Register Instructions
3882 0.63,6.FRT,11./,16./,21.583,31.Rc:X:f::Move From FPSCR
3884 0.63,6.BF,9./,11.BFA,14./,16./,21.64,31./:X:f::Move to Condition Register from FPSCR
3886 0.64,6.BF,9./,11./,16.U,20./,21.134,31.Rc:X:f::Move To FPSCR Field Immediate
3888 0.63,6./,7.FLM,15./,16.FRB,21.711,31.Rc:XFL:f::Move To FPSCR Fields
3890 0.63,6.BT,11./,16./,21.70,31.Rc:X:f::Move To FPSCR Bit 0
3892 0.63,6.BT,11./,16./,21.38,31.Rc:X:f::Move To FPSCR Bit 1
3896 # I.A.1.1 Floating-Point Store Instruction
3898 0.31,6.FRS,11.RA,16.RB,21.983,31./:X:f::Store Floating-Point as Integer Word Indexed
3901 # I.A.1.2 Floating-Point Arithmetic Instructions
3904 0.63,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f::Floating Square Root
3906 0.59,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f::Floating Square Root Single
3908 0.59,6.FRT,11./,16.FRB,21./,26.24,31.Rc:A:f::Floating Reciprocal Estimate Single
3910 0.63,6.FRT,11./,16.FRB,21./,26.26,31.Rc:A:f::Floating Reciprocal Square Root Estimate
3913 # I.A.1.3 Floating-Point Select Instruction
3916 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.23,31.Rc:A:f::Floating Select
3920 # II.3.2 Cache Management Instructions
3923 0.31,6./,11.RA,16.RB,21.982,31./:X::icbi:Instruction Cache Block Invalidate
3924 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3925 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3926 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3927 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
3928 /* blindly flush all instruction cache entries */
3929 #if WITH_IDECODE_CACHE_SIZE
3930 cpu_flush_icache(processor);
3933 0.19,6./,11./,16./,21.150,31./:XL::isync:Instruction Synchronize
3934 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3935 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3936 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3937 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
3938 cpu_synchronize_context(processor);
3942 # II.3.2.2 Data Cache Instructions
3945 0.31,6./,11.RA,16.RB,21.278,31./:X:::Data Cache Block Touch
3946 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3947 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
3948 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
3949 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
3950 TRACE(trace_tbd,("Data Cache Block Touch\n"));
3952 0.31,6./,11.RA,16.RB,21.246,31./:X:::Data Cache Block Touch for Store
3953 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3954 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
3955 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
3956 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3957 TRACE(trace_tbd,("Data Cache Block Touch for Store\n"));
3959 0.31,6./,11.RA,16.RB,21.1014,31./:X:::Data Cache Block set to Zero
3960 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3961 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 10, 10, 0
3962 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 10, 10, 0
3963 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3964 TRACE(trace_tbd,("Data Cache Block set to Zero\n"));
3966 0.31,6./,11.RA,16.RB,21.54,31./:X:::Data Cache Block Store
3967 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3968 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
3969 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
3970 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
3971 TRACE(trace_tbd,("Data Cache Block Store\n"));
3973 0.31,6./,11.RA,16.RB,21.86,31./:X:::Data Cache Block Flush
3974 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3975 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
3976 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
3977 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
3978 TRACE(trace_tbd,("Data Cache Block Flush\n"));
3981 # II.3.3 Enforce In-order Execution of I/O Instruction
3984 0.31,6./,11./,16./,21.854,31./:X::eieio:Enforce In-order Execution of I/O
3985 /* Since this model has no instruction overlap
3986 this instruction need do nothing */
3989 # II.4.1 Time Base Instructions
3992 0.31,6.RT,11.tbr,21.371,31./:XFX::mftb:Move From Time Base
3993 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3994 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3995 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
3996 int n = (tbr{5:9} << 5) | tbr{0:4};
3998 if (is_64bit_implementation) *rT = TB;
3999 else *rT = EXTRACTED64(TB, 32, 63);
4001 else if (n == 269) {
4002 if (is_64bit_implementation) *rT = EXTRACTED64(TB, 0, 31);
4003 else *rT = EXTRACTED64(TB, 0, 31);
4006 program_interrupt(processor, cia,
4007 illegal_instruction_program_interrupt);
4011 # III.2.3.1 System Linkage Instructions
4014 0.19,6./,11./,16./,21.50,31./:XL::rfi:Return From Interrupt
4015 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4016 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4017 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4018 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
4019 if (IS_PROBLEM_STATE(processor)) {
4020 program_interrupt(processor, cia,
4021 privileged_instruction_program_interrupt);
4024 MSR = (MASKED(SRR1, 0, 32)
4025 | MASKED(SRR1, 37, 41)
4026 | MASKED(SRR1, 48, 63));
4027 NIA = MASKED(SRR0, 0, 61);
4028 cpu_synchronize_context(processor);
4032 # III.3.4.1 Move to/from System Register Instructions
4035 #0.31,6.RS,11.spr,21.467,31./:XFX:::Move To Special Purpose Register
4036 #0.31,6.RT,11.spr,21.339,31./:XFX:::Move From Special Purpose Register
4037 0.31,6.RS,11./,16./,21.146,31./:X:::Move To Machine State Register
4038 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4039 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4040 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4041 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4042 if (IS_PROBLEM_STATE(processor))
4043 program_interrupt(processor, cia,
4044 privileged_instruction_program_interrupt);
4048 0.31,6.RT,11./,16./,21.83,31./:X:::Move From Machine State Register
4049 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4050 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
4051 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
4052 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
4053 if (IS_PROBLEM_STATE(processor))
4054 program_interrupt(processor, cia,
4055 privileged_instruction_program_interrupt);
4061 # III.4.11.1 Cache Management Instructions
4064 0.31,6./,11.RA,16.RB,21.470,31./:X::dcbi:Data Cache Block Invalidate
4065 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4066 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4067 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4068 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4069 if (IS_PROBLEM_STATE(processor))
4070 program_interrupt(processor, cia,
4071 privileged_instruction_program_interrupt);
4073 TRACE(trace_tbd,("Data Cache Block Invalidate\n"));
4076 # III.4.11.2 Segment Register Manipulation Instructions
4079 0.31,6.RS,11./,12.SR,16./,21.210,31./:X:32:mtsr %SR,%RS:Move To Segment Register
4080 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4081 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4082 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4083 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4084 if (IS_PROBLEM_STATE(processor))
4085 program_interrupt(processor, cia,
4086 privileged_instruction_program_interrupt);
4090 0.31,6.RS,11./,16.RB,21.242,31./:X:32:mtsrin %RS,%RB:Move To Segment Register Indirect
4091 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4092 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4093 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4094 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4095 if (IS_PROBLEM_STATE(processor))
4096 program_interrupt(processor, cia,
4097 privileged_instruction_program_interrupt);
4099 SEGREG(EXTRACTED32(*rB, 0, 3)) = *rS;
4101 0.31,6.RT,11./,12.SR,16./,21.595,31./:X:32:mfsr %RT,%RS:Move From Segment Register
4102 *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
4103 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4104 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4105 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4106 if (IS_PROBLEM_STATE(processor))
4107 program_interrupt(processor, cia,
4108 privileged_instruction_program_interrupt);
4112 0.31,6.RT,11./,16.RB,21.659,31./:X:32:mfsrin %RT,%RB:Move From Segment Register Indirect
4113 *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
4114 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4115 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4116 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4117 if (IS_PROBLEM_STATE(processor))
4118 program_interrupt(processor, cia,
4119 privileged_instruction_program_interrupt);
4121 *rT = SEGREG(EXTRACTED32(*rB, 0, 3));
4125 # III.4.11.3 Lookaside Buffer Management Instructions (Optional)
4128 0.31,6./,11./,16.RB,21.434,31./:X:64::SLB Invalidate Entry
4130 0.31,6./,11./,16./,21.498,31./:X:64::SLB Invalidate All
4132 0.31,6./,11./,16.RB,21.306,31./:X:::TLB Invalidate Entry
4134 0.31,6./,11./,16./,21.370,31./:X:::TLB Invalidate All
4136 0.31,6./,11./,16./,21.566,31./:X:::TLB Sychronize
4140 # III.A.1.2 External Access Instructions
4143 0.31,6.RT,11.RA,16.RB,21.310,31./:X:earwax::External Control In Word Indexed
4145 0.31,6.RS,11.RA,16.RB,21.438,31./:X:earwax::External Control Out Word Indexed