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 model_data *::model-function::model_create:cpu *processor
588 model_data *model_ptr = ZALLOC(model_data);
589 ASSERT(CURRENT_MODEL > 0 && CURRENT_MODEL < nr_models);
590 model_ptr->name = model_name[CURRENT_MODEL];
591 model_ptr->timing = model_time_mapping[CURRENT_MODEL];
592 model_ptr->processor = processor;
593 model_ptr->nr_cycles = 1;
596 void::model-function::model_init:model_data *model_ptr
598 void::model-function::model_halt:model_data *model_ptr
599 /* Let pipeline drain */
600 while (model_ptr->busy_list)
601 model_new_cycle(model_ptr);
603 model_print *::model-function::model_mon_info:model_data *model_ptr
608 head = tail = ZALLOC(model_print);
609 tail->count = model_ptr->nr_cycles;
610 tail->name = "cycle";
611 tail->suffix_plural = "s";
612 tail->suffix_singular = "";
614 if (model_ptr->nr_stalls_data) {
615 tail->next = ZALLOC(model_print);
617 tail->count = model_ptr->nr_stalls_data;
618 tail->name = "stall";
619 tail->suffix_plural = "s waiting for data";
620 tail->suffix_singular = " waiting for data";
623 if (model_ptr->nr_stalls_unit) {
624 tail->next = ZALLOC(model_print);
626 tail->count = model_ptr->nr_stalls_unit;
627 tail->name = "stall";
628 tail->suffix_plural = "s waiting for a function unit";
629 tail->suffix_singular = " waiting for a function unit";
632 if (model_ptr->nr_stalls_serialize) {
633 tail->next = ZALLOC(model_print);
635 tail->count = model_ptr->nr_stalls_serialize;
636 tail->name = "stall";
637 tail->suffix_plural = "s waiting for serialization";
638 tail->suffix_singular = " waiting for serialization";
641 if (model_ptr->nr_insns_not_handled) {
642 tail->next = ZALLOC(model_print);
644 tail->count = model_ptr->nr_insns_not_handled;
645 tail->name = "instruction";
646 tail->suffix_plural = "s that were not accounted for in timing info";
647 tail->suffix_singular = " that was not accounted for in timing info";
650 if (model_ptr->nr_branches) {
651 tail->next = ZALLOC(model_print);
653 tail->count = model_ptr->nr_branches;
654 tail->name = "branch";
655 tail->suffix_plural = "es";
656 tail->suffix_singular = "";
659 if (model_ptr->nr_branches_fallthrough) {
660 tail->next = ZALLOC(model_print);
662 tail->count = model_ptr->nr_branches_fallthrough;
663 tail->name = "conditional branch";
664 tail->suffix_plural = "es fell through";
665 tail->suffix_singular = " fell through";
668 if (model_ptr->nr_branch_predict_trues) {
669 tail->next = ZALLOC(model_print);
671 tail->count = model_ptr->nr_branch_predict_trues;
672 tail->name = "successful branch prediction";
673 tail->suffix_plural = "s";
674 tail->suffix_singular = "";
677 if (model_ptr->nr_branch_predict_falses) {
678 tail->next = ZALLOC(model_print);
680 tail->count = model_ptr->nr_branch_predict_falses;
681 tail->name = "unsuccessful branch prediction";
682 tail->suffix_plural = "s";
683 tail->suffix_singular = "";
686 for (i = PPC_UNIT_BAD; i < nr_ppc_function_units; i++) {
687 if (model_ptr->nr_units[i]) {
688 tail->next = ZALLOC(model_print);
690 tail->count = model_ptr->nr_units[i];
691 tail->name = ppc_function_unit_name[i];
692 tail->suffix_plural = "s";
693 tail->suffix_singular = "";
697 tail->next = (model_print *)0;
700 void::model-function::model_mon_info_free:model_data *model_ptr, model_print *ptr
702 model_print *next = ptr->next;
707 void::model-function::model_branches:model_data *model_ptr, int failed
708 model_ptr->nr_units[PPC_UNIT_BPU]++;
709 model_ptr->insn_handled = 1;
711 model_ptr->nr_branches_fallthrough++;
713 model_ptr->nr_branches++;
714 model_new_cycle(model_ptr); /* A branch always ends the current cycle */
716 void::model-function::model_branch_predict:model_data *model_ptr, int success
718 model_ptr->nr_branch_predict_trues++;
720 model_ptr->nr_branch_predict_falses++;
722 # The following (illegal) instruction is `known' by gen and is
723 # called when ever an illegal instruction is encountered
725 program_interrupt(processor, cia,
726 illegal_instruction_program_interrupt);
730 # The following (floating point unavailable) instruction is `known' by gen
731 # and is called when ever an a floating point instruction is to be
732 # executed but floating point is make unavailable by the MSR
733 ::internal::floating_point_unavailable
734 floating_point_unavailable_interrupt(processor, cia);
739 # Floating point support functions
742 # Convert 32bit single to 64bit double
743 unsigned64::function::DOUBLE:unsigned32 WORD
745 if (EXTRACTED32(WORD, 1, 8) > 0
746 && EXTRACTED32(WORD, 1, 8) < 255) {
747 /* normalized operand */
748 int not_word_1_1 = !EXTRACTED32(WORD, 1, 1); /*2.6.3 bug*/
749 FRT = (INSERTED64(EXTRACTED32(WORD, 0, 1), 0, 1)
750 | INSERTED64(not_word_1_1, 2, 2)
751 | INSERTED64(not_word_1_1, 3, 3)
752 | INSERTED64(not_word_1_1, 4, 4)
753 | INSERTED64(EXTRACTED32(WORD, 2, 31), 5, (63 - 29)));
755 else if (EXTRACTED32(WORD, 1, 8) == 0
756 && EXTRACTED32(WORD, 9, 31) != 0) {
757 /* denormalized operand */
758 int sign = EXTRACTED32(WORD, 0, 0);
760 unsigned64 frac = INSERTED64(EXTRACTED32(WORD, 9, 31), 1, (52 - 29));
761 /* normalize the operand */
762 while (MASKED64(frac, 0, 0) == 0) {
766 FRT = (INSERTED64(sign, 0, 0)
767 | INSERTED64(exp + 1023, 1, 11)
768 | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
770 else if (EXTRACTED32(WORD, 1, 8) == 255
771 || EXTRACTED32(WORD, 1, 31) == 0) {
772 FRT = (INSERTED64(EXTRACTED32(WORD, 0, 1), 0, 1)
773 | INSERTED64(EXTRACTED32(WORD, 1, 1), 2, 2)
774 | INSERTED64(EXTRACTED32(WORD, 1, 1), 3, 3)
775 | INSERTED64(EXTRACTED32(WORD, 1, 1), 4, 4)
776 | INSERTED64(EXTRACTED32(WORD, 2, 31), 5, (63 - 29)));
779 error("DOUBLE - unknown case\n");
784 # Convert 64bit single to 32bit double
785 unsigned32::function::SINGLE:unsigned64 FRS
787 if (EXTRACTED64(FRS, 1, 11) > 896
788 || EXTRACTED64(FRS, 1, 63) == 0) {
789 /* no denormalization required (includes Zero/Infinity/NaN) */
790 WORD = (INSERTED32(EXTRACTED64(FRS, 0, 1), 0, 1)
791 | INSERTED32(EXTRACTED64(FRS, 5, 34), 2, 31));
793 else if (874 <= EXTRACTED64(FRS, 1, 11)
794 && EXTRACTED64(FRS, 1, 11) <= 896) {
795 /* denormalization required */
796 int sign = EXTRACTED64(FRS, 0, 0);
797 int exp = EXTRACTED64(FRS, 1, 11) - 1023;
798 unsigned64 frac = (BIT64(0)
799 | INSERTED64(EXTRACTED64(FRS, 12, 63), 1, 52));
800 /* denormalize the operand */
802 frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63);
805 WORD = (INSERTED32(sign, 0, 0)
806 | INSERTED32(0x00, 1, 8)
807 | INSERTED32(EXTRACTED64(frac, 1, 23), 9, 31));
810 WORD = 0x0; /* ??? */
815 # round 64bit double to 64bit but single
816 void::function::Round_Single:cpu *processor, int sign, int *exp, unsigned64 *frac_grx
817 /* comparisons ignore u bits */
820 int lsb = EXTRACTED64(*frac_grx, 23, 23);
821 int gbit = EXTRACTED64(*frac_grx, 24, 24);
822 int rbit = EXTRACTED64(*frac_grx, 25, 25);
823 int xbit = EXTRACTED64(*frac_grx, 26, 55) != 0;
824 if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
825 if (lsb == 1 && gbit == 1) inc = 1;
826 if (lsb == 0 && gbit == 1 && rbit == 1) inc = 1;
827 if (lsb == 0 && gbit == 1 && xbit == 1) inc = 1;
829 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_pos_infinity) {
830 if (sign == 0 && gbit == 1) inc = 1;
831 if (sign == 0 && rbit == 1) inc = 1;
832 if (sign == 0 && xbit == 1) inc = 1;
834 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_neg_infinity) {
835 if (sign == 1 && gbit == 1) inc = 1;
836 if (sign == 1 && rbit == 1) inc = 1;
837 if (sign == 1 && xbit == 1) inc = 1;
839 /* work out addition in low 25 bits of out */
840 out = EXTRACTED64(*frac_grx, 0, 23) + inc;
841 *frac_grx = INSERTED64(out, 0, 23);
842 if (out & BIT64(64 - 23 - 1 - 1)) {
843 *frac_grx = (BIT64(0) |
844 INSERTED64(EXTRACTED64(*frac_grx, 0, 22), 1, 23));
847 /* frac_grx[24:52] = 0 already */
849 FPSCR_SET_FI(gbit || rbit || xbit);
853 void::function::Round_Integer:cpu *processor, int sign, unsigned64 *frac, int *frac64, int gbit, int rbit, int xbit, fpscreg round_mode
855 if (round_mode == fpscr_rn_round_to_nearest) {
856 if (*frac64 == 1 && gbit == 1) inc = 1;
857 if (*frac64 == 0 && gbit == 1 && rbit == 1) inc = 1;
858 if (*frac64 == 0 && gbit == 1 && xbit == 1) inc = 1;
860 if (round_mode == fpscr_rn_round_towards_pos_infinity) {
861 if (sign == 0 && gbit == 1) inc = 1;
862 if (sign == 0 && rbit == 1) inc = 1;
863 if (sign == 0 && xbit == 1) inc = 1;
865 if (round_mode == fpscr_rn_round_towards_neg_infinity) {
866 if (sign == 1 && gbit == 1) inc = 1;
867 if (sign == 1 && rbit == 1) inc = 1;
868 if (sign == 1 && xbit == 1) inc = 1;
870 /* frac[0:64] = frac[0:64} + inc */
871 *frac += (*frac64 && inc ? 1 : 0);
872 *frac64 = (*frac64 + inc) & 0x1;
874 FPSCR_SET_FI(gbit | rbit | xbit);
877 void::function::Round_Float:cpu *processor, int sign, int *exp, unsigned64 *frac, fpscreg round_mode
880 int lsb = EXTRACTED64(*frac, 52, 52);
881 int gbit = EXTRACTED64(*frac, 53, 53);
882 int rbit = EXTRACTED64(*frac, 54, 54);
883 int xbit = EXTRACTED64(*frac, 55, 55);
884 if (round_mode == fpscr_rn_round_to_nearest) {
885 if (lsb == 1 && gbit == 1) inc = 1;
886 if (lsb == 0 && gbit == 1 && rbit == 1) inc = 1;
887 if (lsb == 0 && gbit == 1 && xbit == 1) inc = 1;
889 if (round_mode == fpscr_rn_round_towards_pos_infinity) {
890 if (sign == 0 && gbit == 1) inc = 1;
891 if (sign == 0 && rbit == 1) inc = 1;
892 if (sign == 0 && xbit == 1) inc = 1;
894 if (round_mode == fpscr_rn_round_towards_neg_infinity) {
895 if (sign == 1 && gbit == 1) inc = 1;
896 if (sign == 1 && rbit == 1) inc = 1;
897 if (sign == 1 && xbit == 1) inc = 1;
899 /* frac//carry_out = frac + inc */
900 *frac = (*frac >> 1) + (INSERTED64(inc, 52, 52) >> 1);
901 carry_out = EXTRACTED64(*frac, 0, 0);
903 if (carry_out == 1) *exp = *exp + 1;
905 FPSCR_SET_FI(gbit | rbit | xbit);
906 FPSCR_SET_XX(FPSCR & fpscr_fi);
909 # conversion of FP to integer
910 void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64 *frt, unsigned64 frb, fpscreg round_mode, int tgt_precision
918 int sign = EXTRACTED64(frb, 0, 0);
919 if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 63) == 0)
920 goto Infinity_Operand;
921 if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 0)
923 if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 1)
925 if (EXTRACTED64(frb, 1, 11) > 1086) goto Large_Operand;
926 if (EXTRACTED64(frb, 1, 11) > 0) exp = EXTRACTED64(frb, 1, 11) - 1023;
927 if (EXTRACTED64(frb, 1, 11) == 0) exp = -1022;
928 if (EXTRACTED64(frb, 1, 11) > 0) { /* normal */
929 frac = BIT64(1) | INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
932 if (EXTRACTED64(frb, 1, 11) == 0) { /* denorm */
933 frac = INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
936 gbit = 0, rbit = 0, xbit = 0;
937 for (i = 1; i <= 63 - exp; i++) {
941 frac64 = EXTRACTED64(frac, 63, 63);
942 frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63);
944 Round_Integer(processor, sign, &frac, &frac64, gbit, rbit, xbit, round_mode);
945 if (sign == 1) { /* frac[0:64] = ~frac[0:64] + 1 */
948 frac += (frac64 ? 1 : 0);
949 frac64 = (frac64 + 1) & 0x1;
951 if (tgt_precision == 32 /* can ignore frac64 in compare */
952 && (signed64)frac > (signed64)MASK64(33+1, 63)/*2^31-1 >>1*/)
954 if (tgt_precision == 64 /* can ignore frac64 in compare */
955 && (signed64)frac > (signed64)MASK64(1+1, 63)/*2^63-1 >>1*/)
957 if (tgt_precision == 32 /* can ignore frac64 in compare */
958 && (signed64)frac < (signed64)MASK64(0, 32+1)/*-2^31 >>1*/)
960 if (tgt_precision == 64 /* can ignore frac64 in compare */
961 && (signed64)frac < (signed64)MASK64(0, 0+1)/*-2^63 >>1*/)
963 FPSCR_SET_XX(FPSCR & fpscr_fi);
964 if (tgt_precision == 32)
965 *frt = MASKED64(*frt, 0, 31) | (EXTRACTED64(frac, 33, 63) << 1) | frac64;
966 if (tgt_precision == 64)
967 *frt = (EXTRACTED64(frac, 1, 63) << 1) | frac64;
968 /*FPSCR[fprf] = undefined */
974 FPSCR_OR_VX(fpscr_vxcvi);
975 if ((FPSCR & fpscr_ve) == 0) {
976 if (tgt_precision == 32) {
977 if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7FFFFFFF;
978 if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
981 if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/
982 if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
984 /* FPSCR[FPRF] = undefined */
991 FPSCR_OR_VX(fpscr_vxsnan | fpscr_vxcvi);
992 if ((FPSCR & fpscr_ve) == 0) {
993 if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
994 if (tgt_precision == 64) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
995 /* FPSCR[fprf] = undefined */
1002 FPSCR_OR_VX(fpscr_vxcvi);
1003 if ((FPSCR & fpscr_ve) == 0) {
1004 if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1005 if (tgt_precision == 64) *frt = BIT64(0);/*0x8000_0000_0000_0000*/
1006 /* FPSCR[fprf] = undefined */
1013 FPSCR_OR_VX(fpscr_vxcvi);
1014 if ((FPSCR & fpscr_ve) == 0) {
1015 if (tgt_precision == 32) {
1016 if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7fffffff;
1017 if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1020 if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/
1021 if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
1023 /* FPSCR[fprf] = undefined */
1029 # extract out raw fields of a FP number
1030 int::function::sign:unsigned64 FRS
1031 return (MASKED64(FRS, 0, 0)
1034 int::function::biased_exp:unsigned64 frs, int single
1036 return EXTRACTED64(frs, 1, 8);
1038 return EXTRACTED64(frs, 1, 11);
1039 unsigned64::function::fraction:unsigned64 frs, int single
1041 return EXTRACTED64(frs, 9, 31);
1043 return EXTRACTED64(frs, 12, 63);
1045 # a number?, each of the below return +1 or -1 (based on sign bit)
1047 int::function::is_nor:unsigned64 frs, int single
1048 int exp = biased_exp(frs, single);
1050 && exp <= (single ? 254 : 2046));
1051 int::function::is_zero:unsigned64 FRS
1052 return (MASKED64(FRS, 1, 63) == 0
1055 int::function::is_den:unsigned64 frs, int single
1056 int exp = biased_exp(frs, single);
1057 unsigned64 frac = fraction(frs, single);
1058 return (exp == 0 && frac != 0
1061 int::function::is_inf:unsigned64 frs, int single
1062 int exp = biased_exp(frs, single);
1063 int frac = fraction(frs, single);
1064 return (exp == (single ? 255 : 2047) && frac == 0
1067 int::function::is_NaN:unsigned64 frs, int single
1068 int exp = biased_exp(frs, single);
1069 int frac = fraction(frs, single);
1070 return (exp == (single ? 255 : 2047) && frac != 0
1073 int::function::is_SNaN:unsigned64 frs, int single
1074 return (is_NaN(frs, single)
1075 && !(frs & (single ? MASK64(9, 9) : MASK64(12, 12)))
1078 int::function::is_QNaN:unsigned64 frs, int single
1079 return (is_NaN(frs, single) && !is_SNaN(frs, single));
1080 int::function::is_less_than:unsigned64 *fra, unsigned64 *frb
1081 return *(double*)fra < *(double*)frb;
1082 int::function::is_greater_than:unsigned64 *fra, unsigned64 *frb
1083 return *(double*)fra > *(double*)frb;
1084 int::function::is_equan_to:unsigned64 *fra, unsigned64 *frb
1085 return *(double*)fra == *(double*)frb;
1088 # which quiet nan should become the result
1089 unsigned64::function::select_qnan:unsigned64 fra, unsigned64 frb, unsigned64 frc, int instruction_is_frsp, int generate_qnan, int single
1091 if (is_NaN(fra, single))
1093 else if (is_NaN(frb, single))
1094 if (instruction_is_frsp)
1095 frt = MASKED64(frb, 0, 34);
1098 else if (is_NaN(frc, single))
1100 else if (generate_qnan)
1101 frt = MASK64(1, 12); /* 0x7FF8_0000_0000_0000 */
1103 error("select_qnan - default reached\n");
1107 # detect invalid operation
1108 int::function::is_invalid_operation:cpu *processor, unsigned_word cia, unsigned64 fra, unsigned64 frb, fpscreg check, int single, int negate
1110 if ((check & fpscr_vxsnan)
1111 && (is_SNaN(fra, single) || is_SNaN(frb, single))) {
1112 FPSCR_OR_VX(fpscr_vxsnan);
1115 if ((check & fpscr_vxisi)
1116 && (is_inf(fra, single) && is_inf(frb, single))
1117 && ((negate && sign(fra) != sign(frb))
1118 || (!negate && sign(fra) == sign(frb)))) {
1119 /*FIXME: don't handle inf-inf VS inf+-inf */
1120 FPSCR_OR_VX(fpscr_vxisi);
1123 if ((check & fpscr_vxidi)
1124 && (is_inf(fra, single) && is_inf(frb, single))) {
1125 FPSCR_OR_VX(fpscr_vxidi);
1128 if ((check & fpscr_vxzdz)
1129 && (is_zero(fra) && is_zero(frb))) {
1130 FPSCR_OR_VX(fpscr_vxzdz);
1133 if ((check & fpscr_vximz)
1134 && (is_zero(fra) && is_inf(frb, single))) {
1135 FPSCR_OR_VX(fpscr_vximz);
1138 if ((check & fpscr_vxvc)
1139 && (is_NaN(fra, single) || is_NaN(frb, single))) {
1140 FPSCR_OR_VX(fpscr_vxvc);
1143 if ((check & fpscr_vxsoft)) {
1144 FPSCR_OR_VX(fpscr_vxsoft);
1147 if ((check & fpscr_vxsqrt)
1149 FPSCR_OR_VX(fpscr_vxsqrt);
1152 /* if ((check && fpscr_vxcvi) {
1153 && (is_inf(fra, single) || is_NaN(fra, single) || is_large(fra, single)))
1154 FPSCR_OR_VX(fpscr_vxcvi);
1164 # handle case of invalid operation
1165 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
1166 if (FPSCR & fpscr_ve) {
1167 /* invalid operation exception enabled */
1171 /* fpscr_FPRF unchanged */
1174 /* invalid operation exception disabled */
1175 if (instruction_is_convert_to_64bit) {
1178 else if (instruction_is_convert_to_32bit) {
1181 else { /* arrith, frsp */
1182 *frt = select_qnan(fra, frb, frc,
1183 instruction_is_frsp, 0/*generate*/, single);
1186 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
1194 # I.2.4.1 Branch Instructions
1196 0.18,6.LI,30.AA,31.LK:I:t::Branch
1197 *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1198 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1199 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1200 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1201 if (AA) NIA = IEA(EXTS(LI_0b00));
1202 else NIA = IEA(CIA + EXTS(LI_0b00));
1203 if (LK) LR = (spreg)CIA+4;
1204 model_branches(cpu_model(processor), 1);
1206 0.16,6.BO,11.BI,16.BD,30.AA,31.LK:B:t::Branch Conditional
1207 *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1208 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1209 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1210 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1211 int M, ctr_ok, cond_ok, succeed;
1213 model_wait_for_cr(cpu_model(processor), BIT32_BI);
1214 if (is_64bit_implementation && is_64bit_mode) M = 0;
1216 if (!BO{2}) CTR = CTR - 1;
1217 ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != (BO{3}));
1218 cond_ok = BO{0} || ((CR{BI}) == (BO{1}));
1219 if (ctr_ok && cond_ok) {
1220 if (AA) NIA = IEA(EXTS(BD_0b00));
1221 else NIA = IEA(CIA + EXTS(BD_0b00));
1226 if (LK) LR = (spreg)IEA(CIA + 4);
1227 model_branches(cpu_model(processor), succeed);
1230 if (BO{4}) { /* branch prediction bit set, reverse sense of test */
1231 reverse = EXTS(BD_0b00) < 0;
1232 } else { /* branch prediction bit not set */
1233 reverse = EXTS(BD_0b00) >= 0;
1235 model_branch_predict(cpu_model(processor), reverse ? !succeed : succeed);
1238 0.19,6.BO,11.BI,16./,21.16,31.LK:XL:t::Branch Conditional to Link Register
1239 *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1240 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1241 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1242 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1243 int M, ctr_ok, cond_ok, succeed;
1244 if (is_64bit_implementation && is_64bit_mode) M = 0;
1247 model_wait_for_cr(cpu_model(processor), BIT32_BI);
1248 if (!BO{2}) CTR = CTR - 1;
1249 ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != BO{3});
1250 cond_ok = BO{0} || (CR{BI} == BO{1});
1251 if (ctr_ok && cond_ok) {
1257 if (LK) LR = (spreg)IEA(CIA + 4);
1258 model_branches(cpu_model(processor), succeed);
1260 model_branch_predict(cpu_model(processor), BO{4} ? !succeed : succeed);
1262 0.19,6.BO,11.BI,16./,21.528,31.LK:XL:t::Branch Conditional to Count Register
1263 *601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1264 *603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1265 *603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1266 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1267 int cond_ok, succeed;
1269 model_wait_for_cr(cpu_model(processor), BIT32_BI);
1270 cond_ok = BO{0} || (CR{BI} == BO{1});
1272 NIA = IEA(CTR_0b00);
1277 if (LK) LR = (spreg)IEA(CIA + 4);
1278 model_branches(cpu_model(processor), succeed);
1280 model_branch_predict(cpu_model(processor), BO{4} ? !succeed : succeed);
1283 # I.2.4.2 System Call Instruction
1285 0.17,6./,11./,16./,30.1,31./:SC:t::System Call
1286 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1287 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
1288 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
1289 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1290 model_serialize(my_index, cpu_model(processor));
1291 system_call_interrupt(processor, cia);
1294 # I.2.4.3 Condition Register Logical Instructions
1296 0.19,6.BT,11.BA,16.BB,21.257,31./:XL::crand:Condition Register AND
1297 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1298 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1299 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1300 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1301 BLIT32(CR, BT, CR{BA} && CR{BB});
1303 0.19,6.BT,11.BA,16.BB,21.449,31./:XL::cror:Condition Register OR
1304 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1305 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1306 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1307 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1308 BLIT32(CR, BT, CR{BA} || CR{BB});
1310 0.19,6.BT,11.BA,16.BB,21.193,31./:XL::crxor:Condition Register XOR
1311 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1312 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1313 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1314 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1315 BLIT32(CR, BT, CR{BA} != CR{BB});
1317 0.19,6.BT,11.BA,16.BB,21.225,31./:XL::crnand:Condition Register NAND
1318 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1319 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1320 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1321 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1322 BLIT32(CR, BT, !(CR{BA} && CR{BB}));
1324 0.19,6.BT,11.BA,16.BB,21.33,31./:XL::crnor:Condition Register NOR
1325 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1326 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1327 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1328 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1329 BLIT32(CR, BT, !(CR{BA} || CR{BB}));
1331 0.19,6.BT,11.BA,16.BB,21.289,31./:XL::creqv:Condition Register Equivalent
1332 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1333 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1334 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1335 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1336 BLIT32(CR, BT, CR{BA} == CR{BB});
1338 0.19,6.BT,11.BA,16.BB,21.129,31./:XL::crandc:Condition Register AND with Complement
1339 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1340 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1341 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1342 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1343 BLIT32(CR, BT, CR{BA} && !CR{BB});
1345 0.19,6.BT,11.BA,16.BB,21.417,31./:XL::crorc:Condition Register OR with Complement
1346 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1347 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1348 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1349 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1350 BLIT32(CR, BT, CR{BA} || !CR{BB});
1353 # I.2.4.4 Condition Register Field Instruction
1355 0.19,6.BF,9./,11.BFA,14./,16./,21.0,31./:XL:::Move Condition Register Field
1356 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1357 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1358 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1359 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1360 MBLIT32(CR, 4*BF, 4*BF+3, EXTRACTED32(CR, 4*BFA, 4*BFA+3));
1364 # I.3.3.2 Fixed-Point Load Instructions
1367 0.34,6.RT,11.RA,16.D:D:::Load Byte and Zero
1368 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1369 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1370 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1371 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1377 *rT = MEM(unsigned, EA, 1);
1379 ppc_insn_int0(my_index, processor, cpu_model(processor), rT, 0/*Rc*/);
1381 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
1384 0.31,6.RT,11.RA,16.RB,21.87,31./:X:::Load Byte and Zero Indexed
1385 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1386 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1387 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1388 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1394 *rT = MEM(unsigned, EA, 1);
1396 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rB, 0/*Rc*/);
1398 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, 0/*Rc*/);
1400 0.35,6.RT,11.RA,16.D:D:::Load Byte and Zero with Update
1401 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1402 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1403 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1404 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1406 if (RA == 0 || RA == RT)
1407 program_interrupt(processor, cia,
1408 illegal_instruction_program_interrupt);
1410 *rT = MEM(unsigned, EA, 1);
1412 ppc_insn_int1_update(my_index, processor, cpu_model(processor), rT, rA);
1414 0.31,6.RT,11.RA,16.RB,21.119,31./:X:::Load Byte and Zero with Update Indexed
1415 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1416 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1417 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1418 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1420 if (RA == 0 || RA == RT)
1421 program_interrupt(processor, cia,
1422 illegal_instruction_program_interrupt);
1424 *rT = MEM(unsigned, EA, 1);
1426 ppc_insn_int2_update(my_index, processor, cpu_model(processor), rT, rA, rB);
1428 0.40,6.RT,11.RA,16.D:D:::Load Halfword and Zero
1429 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1430 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1431 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1432 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1438 *rT = MEM(unsigned, EA, 2);
1440 ppc_insn_int0(my_index, processor, cpu_model(processor), rT, 0/*Rc*/);
1442 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
1444 0.31,6.RT,11.RA,16.RB,21.279,31./:X:::Load Halfword and Zero Indexed
1445 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1446 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1447 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1448 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1454 *rT = MEM(unsigned, EA, 2);
1456 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rB, 0/*Rc*/);
1458 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, 0/*Rc*/);
1460 0.41,6.RT,11.RA,16.D:D:::Load Halfword and Zero with Update
1461 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1462 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1463 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1464 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1466 if (RA == 0 || RA == RT)
1467 program_interrupt(processor, cia,
1468 illegal_instruction_program_interrupt);
1470 *rT = MEM(unsigned, EA, 2);
1472 ppc_insn_int1_update(my_index, processor, cpu_model(processor), rT, rA);
1474 0.31,6.RT,11.RA,16.RB,21.311,31./:X:::Load Halfword and Zero with Update Indexed
1475 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1476 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1477 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1478 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1480 if (RA == 0 || RA == RT)
1481 program_interrupt(processor, cia,
1482 illegal_instruction_program_interrupt);
1484 *rT = MEM(unsigned, EA, 2);
1486 ppc_insn_int2_update(my_index, processor, cpu_model(processor), rT, rA, rB);
1488 0.42,6.RT,11.RA,16.D:D:::Load Halfword Algebraic
1489 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1490 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1491 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1492 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1498 *rT = MEM(signed, EA, 2);
1500 ppc_insn_int0(my_index, processor, cpu_model(processor), rT, 0/*Rc*/);
1502 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
1504 0.31,6.RT,11.RA,16.RB,21.343,31./:X:::Load Halfword Algebraic Indexed
1505 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1506 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1507 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1508 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1514 *rT = MEM(signed, EA, 2);
1516 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rB, 0/*Rc*/);
1518 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, 0/*Rc*/);
1520 0.43,6.RT,11.RA,16.D:D:::Load Halfword Algebraic with Update
1521 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1522 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1523 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1524 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1526 if (RA == 0 || RA == RT)
1527 program_interrupt(processor, cia,
1528 illegal_instruction_program_interrupt);
1530 *rT = MEM(signed, EA, 2);
1531 ppc_insn_int1_update(my_index, processor, cpu_model(processor), rT, rA);
1533 0.31,6.RT,11.RA,16.RB,21.375,31./:X:::Load Halfword Algebraic with Update Indexed
1534 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1535 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1536 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1537 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1539 if (RA == 0 || RA == RT)
1540 program_interrupt(processor, cia,
1541 illegal_instruction_program_interrupt);
1543 *rT = MEM(signed, EA, 2);
1545 ppc_insn_int2_update(my_index, processor, cpu_model(processor), rT, rA, rB);
1547 0.32,6.RT,11.RA,16.D:D:::Load Word and Zero
1548 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1549 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1550 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1551 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1557 *rT = MEM(unsigned, EA, 4);
1559 ppc_insn_int0(my_index, processor, cpu_model(processor), rT, 0/*Rc*/);
1561 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
1563 0.31,6.RT,11.RA,16.RB,21.23,31./:X:::Load Word and Zero Indexed
1564 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1565 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1566 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1567 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1573 *rT = MEM(unsigned, EA, 4);
1575 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rB, 0/*Rc*/);
1577 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, 0/*Rc*/);
1579 0.33,6.RT,11.RA,16.D:D:::Load Word and Zero with Update
1580 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1581 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1582 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1583 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1585 if (RA == 0 || RA == RT)
1586 program_interrupt(processor, cia,
1587 illegal_instruction_program_interrupt);
1589 *rT = MEM(unsigned, EA, 4);
1591 ppc_insn_int1_update(my_index, processor, cpu_model(processor), rT, rA);
1593 0.31,6.RT,11.RA,16.RB,21.55,31./:X:::Load Word and Zero with Update Indexed
1594 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1595 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1596 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1597 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1599 if (RA == 0 || RA == RT)
1600 program_interrupt(processor, cia,
1601 illegal_instruction_program_interrupt);
1603 *rT = MEM(unsigned, EA, 4);
1605 ppc_insn_int2_update(my_index, processor, cpu_model(processor), rT, rA, rB);
1607 0.58,6.RT,11.RA,16.DS,30.2:DS:64::Load Word Algebraic
1610 # if (RA == 0) b = 0;
1612 # EA = b + EXTS(DS_0b00);
1613 # *rT = MEM(signed, EA, 4);
1615 0.31,6.RT,11.RA,16.RB,21.341,31./:X:64::Load Word Algebraic Indexed
1618 # if (RA == 0) b = 0;
1621 # *rT = MEM(signed, EA, 4);
1623 0.31,6.RT,11.RA,16.RB,21.373,31./:X:64::Load Word Algebraic with Update Indexed
1625 # if (RA == 0 || RA == RT)
1626 # program_interrupt(processor, cia
1627 # illegal_instruction_program_interrupt);
1629 # *rT = MEM(signed, EA, 4);
1632 0.58,6.RT,11.RA,16.DS,30.0:DS:64::Load Doubleword
1635 # if (RA == 0) b = 0;
1637 # EA = b + EXTS(DS_0b00);
1638 # *rT = MEM(unsigned, EA, 8);
1640 0.31,6.RT,11.RA,16.RB,21.21,31./:X:64::Load Doubleword Indexed
1643 # if (RA == 0) b = 0;
1646 # *rT = MEM(unsigned, EA, 8);
1648 0.58,6.RT,11.RA,16.DS,30.1:DS:64::Load Doubleword with Update
1650 # if (RA == 0 || RA == RT)
1651 # program_interrupt(processor, cia
1652 # illegal_instruction_program_interrupt);
1653 # EA = *rA + EXTS(DS_0b00);
1654 # *rT = MEM(unsigned, EA, 8);
1657 0.31,6.RT,11.RA,16.RB,21.53,31./:DS:64::Load Doubleword with Update Indexed
1659 # if (RA == 0 || RA == RT)
1660 # program_interrupt(processor, cia
1661 # illegal_instruction_program_interrupt);
1663 # *rT = MEM(unsigned, EA, 8);
1669 # I.3.3.3 Fixed-Point Store Instructions
1672 0.38,6.RS,11.RA,16.D:D:::Store Byte
1673 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1674 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1675 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1676 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1684 ppc_insn_int0_noout(my_index, processor, cpu_model(processor));
1686 ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rA);
1688 0.31,6.RS,11.RA,16.RB,21.215,31./:X:::Store Byte Indexed
1689 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1690 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1691 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1692 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1700 ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
1702 ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
1704 0.39,6.RS,11.RA,16.D:D:::Store Byte with Update
1705 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1706 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1707 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1708 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1711 program_interrupt(processor, cia,
1712 illegal_instruction_program_interrupt);
1716 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rA, 0/*Rc*/);
1718 0.31,6.RS,11.RA,16.RB,21.247,31./:X:::Store Byte with Update Indexed
1719 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1720 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1721 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1722 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1725 program_interrupt(processor, cia,
1726 illegal_instruction_program_interrupt);
1730 ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rA, rB, 0/*Rc*/);
1732 0.44,6.RS,11.RA,16.D:D:::Store Half Word
1733 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1734 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1735 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1736 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1744 ppc_insn_int0_noout(my_index, processor, cpu_model(processor));
1746 ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rA);
1748 0.31,6.RS,11.RA,16.RB,21.407,31./:X:::Store Half Word Indexed
1749 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1750 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1751 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1752 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1760 ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
1762 ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
1764 0.45,6.RS,11.RA,16.D:D:::Store Half Word with Update
1765 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1766 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1767 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1768 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1771 program_interrupt(processor, cia,
1772 illegal_instruction_program_interrupt);
1776 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rA, 0/*Rc*/);
1778 0.31,6.RS,11.RA,16.RB,21.439,31./:X:::Store Half Word with Update Indexed
1779 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1780 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1781 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1782 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1785 program_interrupt(processor, cia,
1786 illegal_instruction_program_interrupt);
1790 ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rA, rB, 0/*Rc*/);
1792 0.36,6.RS,11.RA,16.D:D:::Store Word
1793 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1794 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1795 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1796 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1804 ppc_insn_int0_noout(my_index, processor, cpu_model(processor));
1806 ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rA);
1808 0.31,6.RS,11.RA,16.RB,21.151,31./:X:::Store Word Indexed
1809 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1810 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1811 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1812 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1820 ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
1822 ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
1824 0.37,6.RS,11.RA,16.D:D:::Store Word with Update
1825 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1826 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1827 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1828 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1831 program_interrupt(processor, cia,
1832 illegal_instruction_program_interrupt);
1836 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rA, 0/*Rc*/);
1838 0.31,6.RS,11.RA,16.RB,21.183,31./:X:::Store Word with Update Indexed
1839 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1840 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1841 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1842 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1845 program_interrupt(processor, cia,
1846 illegal_instruction_program_interrupt);
1850 ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rA, rB, 0/*Rc*/);
1852 0.62,6.RS,11.RA,16.DS,30.0:DS:64::Store Doubleword
1855 # if (RA == 0) b = 0;
1857 # EA = b + EXTS(DS_0b00);
1858 # STORE(EA, 8, *rS);
1859 0.31,6.RS,11.RA,16.RB,21.149,31./:X:64::Store Doubleword Indexed
1862 # if (RA == 0) b = 0;
1865 # STORE(EA, 8, *rS);
1866 0.62,6.RS,11.RA,16.DS,30.1:DS:64::Store Doubleword with Update
1869 # program_interrupt(processor, cia
1870 # illegal_instruction_program_interrupt);
1871 # EA = *rA + EXTS(DS_0b00);
1872 # STORE(EA, 8, *rS);
1874 0.31,6.RS,11.RA,16.RB,21.181,31./:X:64::Store Doubleword with Update Indexed
1877 # program_interrupt(processor, cia
1878 # illegal_instruction_program_interrupt);
1880 # STORE(EA, 8, *rS);
1885 # I.3.3.4 Fixed-Point Load and Store with Byte Reversal Instructions
1888 0.31,6.RT,11.RA,16.RB,21.790,31./:X:::Load Halfword Byte-Reverse Indexed
1889 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1890 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1891 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1892 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1898 *rT = SWAP_2(MEM(unsigned, EA, 2));
1900 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rB, 0/*Rc*/);
1902 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, 0/*Rc*/);
1904 0.31,6.RT,11.RA,16.RB,21.534,31./:X:::Load Word Byte-Reverse Indexed
1905 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1906 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1907 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1908 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1914 *rT = SWAP_4(MEM(unsigned, EA, 4));
1916 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rB, 0/*Rc*/);
1918 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, 0/*Rc*/);
1920 0.31,6.RS,11.RA,16.RB,21.918,31./:X:::Store Half Word Byte-Reversed Indexed
1921 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1922 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1923 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1924 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1930 STORE(EA, 2, SWAP_2(*rS));
1932 ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
1934 ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
1936 0.31,6.RS,11.RA,16.RB,21.662,31./:X:::Store Word Byte-Reversed Indexed
1937 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1938 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1939 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1940 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1946 STORE(EA, 4, SWAP_4(*rS));
1948 ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
1950 ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
1954 # I.3.3.5 Fixed-Point Load and Store Multiple Instrctions
1957 0.46,6.RT,11.RA,16.D:D:be::Load Multiple Word
1959 0.47,6.RS,11.RA,16.D:D:be::Store Multiple Word
1963 # I.3.3.6 Fixed-Point Move Assist Instructions
1966 0.31,6.RT,11.RA,16.NB,21.597,31./:X:be::Load String Word Immediate
1968 0.31,6.RT,11.RA,16.RB,21.533,31./:X:be::Load String Word Indexed
1970 0.31,6.RS,11.RA,16.NB,21.725,31./:X:be::Store String Word Immedate
1972 0.31,6.RS,11.RA,16.RB,21.661,31./:X:be::Store String Word Indexed
1976 # I.3.3.7 Storage Synchronization Instructions
1978 # HACK: Rather than monitor addresses looking for a reason
1979 # to cancel a reservation. This code instead keeps
1980 # a copy of the data read from memory. Before performing
1981 # a store, the memory area is checked to see if it has
1983 0.31,6.RT,11.RA,16.RB,21.20,31./:X:::Load Word And Reserve Indexed
1984 *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
1985 *603: PPC_UNIT_LSU, PPC_UNIT_IU, 1, 2, 0
1986 *603e:PPC_UNIT_LSU, PPC_UNIT_IU, 1, 2, 0
1987 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1994 RESERVE_ADDR = real_addr(EA, 1/*is-read?*/);
1995 RESERVE_DATA = MEM(unsigned, EA, 4);
1998 0.31,6.RT,11.RA,16.RB,21.84,31./:X:64::Load Doubleword And Reserve Indexed
2005 RESERVE_ADDR = real_addr(EA, 1/*is-read?*/);
2006 RESERVE_DATA = MEM(unsigned, EA, 8);
2009 0.31,6.RS,11.RA,16.RB,21.150,31.1:X:::Store Word Conditional Indexed
2010 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2011 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 8, 8, 0
2012 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 8, 8, 0
2013 *604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 3, 0
2020 if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/)
2021 && /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 4)) {
2023 CR_SET_XER_SO(0, cr_i_zero);
2026 /* ment to randomly to store, we never do! */
2027 CR_SET_XER_SO(0, 0);
2032 CR_SET_XER_SO(0, 0);
2034 0.31,6.RS,11.RA,16.RB,21.214,31.1:X:64::Store Doubleword Conditional Indexed
2041 if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/)
2042 && /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 8)) {
2044 CR_SET_XER_SO(0, cr_i_zero);
2047 /* ment to randomly to store, we never do */
2048 CR_SET_XER_SO(0, 0);
2053 CR_SET_XER_SO(0, 0);
2056 0.31,6./,11./,16./,21.598,31./:X::sync:Synchronize
2057 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2058 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
2059 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
2060 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
2065 # I.3.3.9 Fixed-Point Arithmetic Instructions
2068 0.14,6.RT,11.RA,16.SI:D:T::Add Immediate
2069 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2070 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2071 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2072 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2075 ppc_insn_int0(my_index, processor, cpu_model(processor), rT, 0/*Rc*/);
2078 *rT = *rA + EXTS(SI);
2079 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
2082 0.15,6.RT,11.RA,16.SI:D:::Add Immediate Shifted
2083 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2084 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2085 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2086 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2088 *rT = EXTS(SI) << 16;
2089 ppc_insn_int0(my_index, processor, cpu_model(processor), rT, 0/*Rc*/);
2092 *rT = *rA + (EXTS(SI) << 16);
2093 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
2096 0.31,6.RT,11.RA,16.RB,21.OE,22.266,31.Rc:XO:::Add
2097 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2098 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2099 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2100 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2103 ALU_END(*rT, 0/*CA*/, OE, Rc);
2104 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2106 0.31,6.RT,11.RA,16.RB,21.OE,22.40,31.Rc:XO:::Subtract From
2107 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2108 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2109 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2110 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2115 ALU_END(*rT, 0/*CA*/, OE, Rc);
2116 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2118 0.12,6.RT,11.RA,16.SI:D:::Add Immediate Carrying
2119 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2120 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2121 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2122 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2125 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
2126 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
2128 0.13,6.RT,11.RA,16.SI:D:::Add Immediate Carrying and Record
2129 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2130 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2131 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2132 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2135 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 1/*Rc*/);
2136 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 1/*Rc*/);
2138 0.8,6.RT,11.RA,16.SI:D:::Subtract From Immediate Carrying
2139 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2140 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2141 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2142 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2147 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
2148 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
2150 0.31,6.RT,11.RA,16.RB,21.OE,22.10,31.Rc:XO:::Add Carrying
2151 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2152 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2153 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2154 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2157 ALU_END(*rT, 1/*CA*/, OE, Rc);
2158 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2160 0.31,6.RT,11.RA,16.RB,21.OE,22.8,31.Rc:XO:::Subtract From Carrying
2161 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2162 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2163 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2164 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2165 /* RT <- ~RA + RB + 1 === RT <- RB - RA */
2170 ALU_END(*rT, 1/*CA*/, OE, Rc);
2171 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2173 0.31,6.RT,11.RA,16.RB,21.OE,22.138,31.Rc:XO:::Add Extended
2174 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2175 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2176 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2177 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2181 ALU_END(*rT, 1/*CA*/, OE, Rc);
2182 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2184 0.31,6.RT,11.RA,16.RB,21.OE,22.136,31.Rc:XO:::Subtract From Extended
2185 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2186 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2187 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2188 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2193 ALU_END(*rT, 1/*CA*/, OE, Rc);
2194 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2196 0.31,6.RT,11.RA,16./,21.OE,22.234,31.Rc:XO:::Add to Minus One Extended
2197 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2198 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2199 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2200 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2204 # ALU_END(*rT, 1/*CA*/, OE, Rc);
2206 0.31,6.RT,11.RA,16./,21.OE,22.232,31.Rc:XO:::Subtract From Minus One Extended
2207 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2208 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2209 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2210 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2215 # ALU_END(*rT, 1/*CA*/, OE, Rc);
2217 0.31,6.RT,11.RA,16./,21.OE,22.202,31.Rc:XO::addze:Add to Zero Extended
2218 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2219 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2220 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2221 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2224 ALU_END(*rT, 1/*CA*/, OE, Rc);
2225 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, Rc);
2227 0.31,6.RT,11.RA,16./,21.OE,22.200,31.Rc:XO:::Subtract from Zero Extended
2228 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2229 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2230 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2231 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2235 ALU_END(*rT, 1/*CA*/, OE, Rc);
2236 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, Rc);
2238 0.31,6.RT,11.RA,16./,21.OE,22.104,31.Rc:XO:::Negate
2239 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2240 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2241 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2242 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2246 ALU_END(*rT,0/*CA*/,OE,Rc);
2247 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, Rc);
2249 0.7,6.RT,11.RA,16.SI:D::mulli:Multiply Low Immediate
2250 *601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2251 *603: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
2252 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
2253 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
2254 signed_word prod = *rA * EXTS(SI);
2256 ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
2258 0.31,6.RT,11.RA,16.RB,21.OE,22.233,31.Rc:D:64::Multiply Low Doubleword
2260 0.31,6.RT,11.RA,16.RB,21.OE,22.235,31.Rc:XO::mullw:Multiply Low Word
2261 *601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2262 *603: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2263 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2264 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0
2265 signed64 a = (signed32)(*rA);
2266 signed64 b = (signed32)(*rB);
2267 signed64 prod = a * b;
2268 signed_word t = prod;
2270 if (t != prod && OE)
2271 XER |= (xer_overflow | xer_summary_overflow);
2272 CR0_COMPARE(t, 0, Rc);
2273 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2275 0.31,6.RT,11.RA,16.RB,21./,22.73,31.Rc:XO:64::Multiply High Doubleword
2277 0.31,6.RT,11.RA,16.RB,21./,22.75,31.Rc:XO::mulhw:Multiply High Word
2278 *601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2279 *603: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2280 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2281 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0
2282 signed64 a = (signed32)(*rA);
2283 signed64 b = (signed32)(*rB);
2284 signed64 prod = a * b;
2285 signed_word t = EXTRACTED64(prod, 0, 31);
2287 CR0_COMPARE(t, 0, Rc);
2288 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2290 0.31,6.RT,11.RA,16.RB,21./,22.9,31.Rc:XO:64::Multiply High Doubleword Unsigned
2292 0.31,6.RT,11.RA,16.RB,21./,22.11,31.Rc:XO::milhwu:Multiply High Word Unsigned
2293 *601: PPC_UNIT_IU, PPC_UNIT_IU, 10, 10, 0
2294 *603: PPC_UNIT_IU, PPC_UNIT_IU, 6, 6, 0
2295 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 6, 6, 0
2296 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0
2297 unsigned64 a = (unsigned32)(*rA);
2298 unsigned64 b = (unsigned32)(*rB);
2299 unsigned64 prod = a * b;
2300 signed_word t = EXTRACTED64(prod, 0, 31);
2302 CR0_COMPARE(t, 0, Rc);
2303 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2305 0.31,6.RT,11.RA,16.RB,21.OE,22.489,31.Rc:XO:64::Divide Doubleword
2307 0.31,6.RT,11.RA,16.RB,21.OE,22.491,31.Rc:XO::divw:Divide Word
2308 *601: PPC_UNIT_IU, PPC_UNIT_IU, 36, 36, 0
2309 *603: PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2310 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2311 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 20, 20, 0
2312 signed64 dividend = (signed32)(*rA);
2313 signed64 divisor = (signed32)(*rB);
2314 if (divisor == 0 /* nb 0x8000..0 is sign extended */
2315 || (dividend == 0x80000000 && divisor == -1)) {
2317 XER |= (xer_overflow | xer_summary_overflow);
2318 CR0_COMPARE(0, 0, Rc);
2321 signed64 quotent = dividend / divisor;
2323 CR0_COMPARE((signed_word)quotent, 0, Rc);
2325 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2327 0.31,6.RT,11.RA,16.RB,21.OE,22.457,31.Rc:XO:64::Divide Doubleword Unsigned
2329 0.31,6.RT,11.RA,16.RB,21.OE,22.459,31.Rc:XO::divwu:Divide Word Unsigned
2330 *601: PPC_UNIT_IU, PPC_UNIT_IU, 36, 36, 0
2331 *603: PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2332 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2333 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 20, 20, 0
2334 unsigned64 dividend = (unsigned32)(*rA);
2335 unsigned64 divisor = (unsigned32)(*rB);
2338 XER |= (xer_overflow | xer_summary_overflow);
2339 CR0_COMPARE(0, 0, Rc);
2342 unsigned64 quotent = dividend / divisor;
2344 CR0_COMPARE((signed_word)quotent, 0, Rc);
2346 ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
2350 # I.3.3.10 Fixed-Point Compare Instructions
2353 0.11,6.BF,9./,10.L,11.RA,16.SI:D:::Compare Immediate
2354 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2355 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2356 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2357 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2358 if (!is_64bit_mode && L)
2359 program_interrupt(processor, cia,
2360 illegal_instruction_program_interrupt);
2363 signed_word b = EXTS(SI);
2368 CR_COMPARE(BF, a, b);
2370 ppc_insn_int1_cr(my_index, processor, cpu_model(processor), BF, rA);
2372 0.31,6.BF,9./,10.L,11.RA,16.RB,21.0,31./:X:::Compare
2373 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2374 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2375 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2376 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2377 if (!is_64bit_mode && L)
2378 program_interrupt(processor, cia,
2379 illegal_instruction_program_interrupt);
2391 CR_COMPARE(BF, a, b);
2393 ppc_insn_int2_cr(my_index, processor, cpu_model(processor), BF, rA, rB);
2395 0.10,6.BF,9./,10.L,11.RA,16.UI:D:::Compare Logical Immediate
2396 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2397 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2398 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2399 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2400 if (!is_64bit_mode && L)
2401 program_interrupt(processor, cia,
2402 illegal_instruction_program_interrupt);
2405 unsigned_word b = UI;
2407 a = MASKED(*rA, 32, 63);
2410 CR_COMPARE(BF, a, b);
2412 ppc_insn_int1_cr(my_index, processor, cpu_model(processor), BF, rA);
2414 0.31,6.BF,9./,10.L,11.RA,16.RB,21.32,31./:X:::Compare Logical
2415 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2416 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2417 *603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2418 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2419 if (!is_64bit_mode && L)
2420 program_interrupt(processor, cia,
2421 illegal_instruction_program_interrupt);
2426 a = MASKED(*rA, 32, 63);
2427 b = MASKED(*rB, 32, 63);
2433 CR_COMPARE(BF, a, b);
2435 ppc_insn_int2_cr(my_index, processor, cpu_model(processor), BF, rA, rB);
2439 # I.3.3.11 Fixed-Point Trap Instructions
2442 0.2,6.TO,11.RA,16.SI:D:64::Trap Doubleword Immediate
2444 program_interrupt(processor, cia,
2445 illegal_instruction_program_interrupt);
2447 signed_word a = *rA;
2448 signed_word b = EXTS(SI);
2449 if ((a < b && TO{0})
2451 || (a == b && TO{2})
2452 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2453 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2455 program_interrupt(processor, cia,
2456 trap_program_interrupt);
2459 0.3,6.TO,11.RA,16.SI:D:::Trap Word Immediate
2460 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2461 *603: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2462 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2463 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2464 signed_word a = EXTENDED(*rA);
2465 signed_word b = EXTS(SI);
2466 if ((a < b && TO{0})
2468 || (a == b && TO{2})
2469 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2470 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2472 program_interrupt(processor, cia,
2473 trap_program_interrupt);
2475 0.31,6.TO,11.RA,16.RB,21.68,31./:X:64::Trap Doubleword
2477 program_interrupt(processor, cia,
2478 illegal_instruction_program_interrupt);
2480 signed_word a = *rA;
2481 signed_word b = *rB;
2482 if ((a < b && TO{0})
2484 || (a == b && TO{2})
2485 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2486 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2488 program_interrupt(processor, cia,
2489 trap_program_interrupt);
2492 0.31,6.TO,11.RA,16.RB,21.4,31./:X:::Trap Word
2493 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2494 *603: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2495 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2496 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2497 signed_word a = EXTENDED(*rA);
2498 signed_word b = EXTENDED(*rB);
2499 if (TO == 12 && rA == rB) {
2500 ITRACE(trace_breakpoint, ("breakpoint\n"));
2501 cpu_halt(processor, cia, was_trap, 0);
2503 else if ((a < b && TO{0})
2505 || (a == b && TO{2})
2506 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2507 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2509 program_interrupt(processor, cia,
2510 trap_program_interrupt);
2513 # I.3.3.12 Fixed-Point Logical Instructions
2516 0.28,6.RS,11.RA,16.UI:D:::AND Immediate
2517 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2518 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2519 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2520 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2522 CR0_COMPARE(*rA, 0, 1/*Rc*/);
2523 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, 1/*Rc*/);
2525 0.29,6.RS,11.RA,16.UI:D:::AND Immediate Shifted
2526 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2527 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2528 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2529 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2530 *rA = *rS & (UI << 16);
2531 CR0_COMPARE(*rA, 0, 1/*Rc*/);
2532 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, 1/*Rc*/);
2534 0.24,6.RS,11.RA,16.UI:D:::OR Immediate
2535 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2536 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2537 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2538 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2540 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, 0);
2542 0.25,6.RS,11.RA,16.UI:D:::OR Immediate Shifted
2543 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2544 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2545 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2546 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2547 *rA = *rS | (UI << 16);
2548 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, 0);
2550 0.26,6.RS,11.RA,16.UI:D:::XOR Immediate
2551 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2552 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2553 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2554 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2556 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, 0);
2558 0.27,6.RS,11.RA,16.UI:D:::XOR Immediate Shifted
2559 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2560 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2561 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2562 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2563 *rA = *rS ^ (UI << 16);
2564 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, 0);
2566 0.31,6.RS,11.RA,16.RB,21.28,31.Rc:X:::AND
2567 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2568 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2569 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2570 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2572 CR0_COMPARE(*rA, 0, Rc);
2573 ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
2575 0.31,6.RS,11.RA,16.RB,21.444,31.Rc:X:::OR
2576 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2577 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2578 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2579 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2581 CR0_COMPARE(*rA, 0, Rc);
2582 ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
2584 0.31,6.RS,11.RA,16.RB,21.316,31.Rc:X:::XOR
2585 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2586 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2587 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2588 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2590 CR0_COMPARE(*rA, 0, Rc);
2591 ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
2593 0.31,6.RS,11.RA,16.RB,21.476,31.Rc:X:::NAND
2594 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2595 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2596 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2597 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2599 CR0_COMPARE(*rA, 0, Rc);
2600 ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
2602 0.31,6.RS,11.RA,16.RB,21.124,31.Rc:X:::NOR
2603 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2604 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2605 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2606 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2608 CR0_COMPARE(*rA, 0, Rc);
2609 ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
2611 0.31,6.RS,11.RA,16.RB,21.284,31.Rc:X:::Equivalent
2612 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2613 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2614 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2615 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2616 # *rA = ~(*rS ^ *rB); /* A === B */
2617 # CR0_COMPARE(*rA, 0, Rc);
2619 0.31,6.RS,11.RA,16.RB,21.60,31.Rc:X:::AND with Complement
2620 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2621 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2622 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2623 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2625 CR0_COMPARE(*rA, 0, Rc);
2626 ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
2628 0.31,6.RS,11.RA,16.RB,21.412,31.Rc:X:::OR with Complement
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./,21.954,31.Rc:X::extsb:Extend Sign Byte
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
2642 *rA = (signed_word)(signed8)*rS;
2643 CR0_COMPARE(*rA, 0, Rc);
2644 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
2646 0.31,6.RS,11.RA,16./,21.922,31.Rc:X::extsh:Extend Sign Half Word
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
2651 *rA = (signed_word)(signed16)*rS;
2652 CR0_COMPARE(*rA, 0, Rc);
2653 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
2655 0.31,6.RS,11.RA,16./,21.986,31.Rc:X:64::Extend Sign Word
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
2660 # *rA = (signed_word)(signed32)*rS;
2661 # CR0_COMPARE(*rA, 0, Rc);
2663 0.31,6.RS,11.RA,16./,21.58,31.Rc:X:64::Count Leading Zeros Doubleword
2665 # unsigned64 mask = BIT64(0);
2666 # unsigned64 source = *rS;
2667 # while (!(source & mask) && mask != 0) {
2672 # CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */
2674 0.31,6.RS,11.RA,16./,21.26,31.Rc:X:::Count Leading Zeros Word
2675 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2676 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2677 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2678 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2680 unsigned32 mask = BIT32(0);
2681 unsigned32 source = *rS;
2682 while (!(source & mask) && mask != 0) {
2687 CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */
2691 # I.3.3.13 Fixed-Point Rotate and Shift Instructions
2694 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
2695 # long n = (sh_5 << 4) | sh_0_4;
2696 # unsigned_word r = ROTL64(*rS, n);
2697 # long b = (mb_5 << 4) | mb_0_4;
2698 # unsigned_word m = MASK(b, 63);
2699 # signed_word result = r & m;
2701 # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
2703 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
2704 # long n = (sh_5 << 4) | sh_0_4;
2705 # unsigned_word r = ROTL64(*rS, n);
2706 # long e = (me_5 << 4) | me_0_4;
2707 # unsigned_word m = MASK(0, e);
2708 # signed_word result = r & m;
2710 # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
2712 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
2713 # long n = (sh_5 << 4) | sh_0_4;
2714 # unsigned_word r = ROTL64(*rS, n);
2715 # long b = (mb_5 << 4) | mb_0_4;
2716 # unsigned_word m = MASK(0, (64-n));
2717 # signed_word result = r & m;
2719 # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
2721 0.21,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M:::Rotate Left Word Immediate then AND with Mask
2722 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2723 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2724 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2725 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2728 unsigned32 r = ROTL32(s, n);
2729 unsigned32 m = MASK(MB+32, ME+32);
2730 signed_word result = r & m;
2732 CR0_COMPARE(result, 0, Rc);
2734 ("n=%d, s=0x%x, r=0x%x, m=0x%x, result=0x%x, cr=0x%x\n",
2735 n, s, r, m, result, CR));
2736 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
2738 0.30,6.RS,11.RA,16.RB,21.mb,27.8,31.Rc:MDS:64::Rotate Left Doubleword then Clear Left
2739 # long n = MASKED(*rB, 58, 63);
2740 # unsigned_word r = ROTL64(*rS, n);
2741 # long b = (mb_5 << 4) | mb_0_4;
2742 # unsigned_word m = MASK(b, 63);
2743 # signed_word result = r & m;
2745 # CR0_COMPARE(result, 0, Rc);
2747 0.30,6.RS,11.RA,16.RB,21.me,27.9,31.Rc:MDS:64::Rotate Left Doubleword then Clear Right
2748 # long n = MASKED(*rB, 58, 63);
2749 # unsigned_word r = ROTL64(*rS, n);
2750 # long e = (me_5 << 4) | me_0_4;
2751 # unsigned_word m = MASK(0, e);
2752 # signed_word result = r & m;
2754 # CR0_COMPARE(result, 0, Rc);
2756 0.23,6.RS,11.RA,16.RB,21.MB,26.ME,31.Rc:M:::Rotate Left Word then AND with Mask
2757 # long n = MASKED(*rB, 59, 63);
2758 # unsigned32 r = ROTL32(*rS, n);
2759 # unsigned32 m = MASK(MB+32, ME+32);
2760 # signed_word result = r & m;
2762 # CR0_COMPARE(result, 0, Rc);
2764 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
2765 # long n = (sh_5 << 4) | sh_0_4;
2766 # unsigned_word r = ROTL64(*rS, n);
2767 # long b = (mb_5 << 4) | mb_0_4;
2768 # unsigned_word m = MASK(b, (64-n));
2769 # signed_word result = (r & m) | (*rA & ~m)
2771 # CR0_COMPARE(result, 0, Rc);
2773 0.20,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M::rlwimi:Rotate Left Word Immediate then Mask Insert
2774 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2775 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2776 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2777 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2779 unsigned32 r = ROTL32(*rS, n);
2780 unsigned32 m = MASK(MB+32, ME+32);
2781 signed_word result = (r & m) | (*rA & ~m);
2783 ITRACE(trace_alu, (": n=%d *rS=0x%x r=0x%x m=0x%x result=0x%x\n",
2784 n, *rS, r, m, result));
2785 CR0_COMPARE(result, 0, Rc);
2786 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
2789 0.31,6.RS,11.RA,16.RB,21.27,31.Rc:X:64::Shift Left Doubleword
2791 0.31,6.RS,11.RA,16.RB,21.24,31.Rc:X:::Shift Left Word
2792 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2793 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2794 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2795 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2796 int n = MASKED(*rB, 59, 63);
2797 unsigned32 source = *rS;
2798 signed_word shifted;
2800 shifted = (source << n);
2804 CR0_COMPARE(shifted, 0, Rc);
2806 ("n=%d, source=0x%x, shifted=0x%x\n",
2807 n, source, shifted));
2808 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
2810 0.31,6.RS,11.RA,16.RB,21.539,31.Rc:X:64::Shift Right Doubleword
2812 0.31,6.RS,11.RA,16.RB,21.536,31.Rc:X:::Shift Right Word
2813 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2814 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2815 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2816 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2817 int n = MASKED(*rB, 59, 63);
2818 unsigned32 source = *rS;
2819 signed_word shifted;
2821 shifted = (source >> n);
2825 CR0_COMPARE(shifted, 0, Rc);
2827 ("n=%d, source=0x%x, shifted=0x%x\n",
2828 n, source, shifted));
2829 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
2831 0.31,6.RS,11.RA,16.sh_0_4,21.413,30.sh_5,31.Rc:XS:64::Shift Right Algebraic Doubleword Immediate
2833 0.31,6.RS,11.RA,16.SH,21.824,31.Rc:X:::Shift Right Algebraic Word Immediate
2834 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2835 *603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2836 *603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2837 *604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2839 signed_word r = ROTL32(*rS, /*64*/32-n);
2840 signed_word m = MASK(n+32, 63);
2841 int S = MASKED(*rS, 32, 32);
2842 signed_word shifted = (r & m) | (S ? ~m : 0);
2844 if (S && ((r & ~m) & MASK(32, 63)) != 0)
2848 CR0_COMPARE(shifted, 0, Rc);
2849 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
2851 0.31,6.RS,11.RA,16.RB,21.794,31.Rc:X:64::Shift Right Algebraic Doubleword
2853 0.31,6.RS,11.RA,16.RB,21.792,31.Rc:X:::Shift Right Algebraic 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, 58, 63);
2859 int shift = (n >= 31 ? 31 : n);
2860 signed32 source = (signed32)*rS; /* signed to keep sign bit */
2861 signed32 shifted = source >> shift;
2862 unsigned32 mask = ((unsigned32)-1) >> (31-shift);
2863 *rA = (signed_word)shifted; /* if 64bit will sign extend */
2864 if (source < 0 && (source & mask))
2868 CR0_COMPARE(shifted, 0, Rc);
2869 ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
2872 # I.3.3.14 Move to/from System Register Instructions
2875 0.31,6.RS,11.spr,21.467,31./:XFX::mtspr %SPR, %RS:Move to Special Purpose Register
2876 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2877 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
2878 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
2879 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
2880 int n = (spr{5:9} << 5) | spr{0:4};
2881 if (spr{0} && IS_PROBLEM_STATE(processor))
2882 program_interrupt(processor, cia,
2883 privileged_instruction_program_interrupt);
2884 else if (!spr_is_valid(n)
2885 || spr_is_readonly(n))
2886 program_interrupt(processor, cia,
2887 illegal_instruction_program_interrupt);
2889 spreg new_val = (spr_length(n) == 64
2891 : MASKED(*rS, 32, 63));
2892 /* HACK - time base registers need to be updated immediatly */
2893 if (WITH_TIME_BASE) {
2897 cpu_set_time_base(processor,
2898 (MASKED64(cpu_get_time_base(processor), 32, 63)
2899 | INSERTED64(new_val, 0, 31)));
2902 cpu_set_time_base(processor,
2903 (MASKED64(cpu_get_time_base(processor), 0, 31)
2904 | INSERTED64(new_val, 32, 63)));
2907 cpu_set_decrementer(processor, new_val);
2918 ppc_insn_to_spr(my_index, processor, cpu_model(processor), n, rS);
2920 0.31,6.RT,11.spr,21.339,31./:XFX::mfspr %RT, %SPR:Move from Special Purpose Register
2921 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2922 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
2923 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
2924 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
2925 int n = (spr{5:9} << 5) | spr{0:4};
2926 if (spr{0} && IS_PROBLEM_STATE(processor))
2927 program_interrupt(processor, cia,
2928 privileged_instruction_program_interrupt);
2929 else if (!spr_is_valid(n))
2930 program_interrupt(processor, cia,
2931 illegal_instruction_program_interrupt);
2933 /* HACK - some SPR's need to get their value extracted specially */
2936 ppc_insn_from_spr(my_index, processor, cpu_model(processor), rT, n);
2938 # FIXME: 604 uses SCIU{1,2} if only one bit is being set
2939 0.31,6.RS,11./,12.FXM,20./,21.144,31./:XFX::mtfcr:Move to Condition Register Fields
2940 *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2941 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
2942 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
2943 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
2948 unsigned_word mask = 0;
2950 for (f = 0; f < 8; f++) {
2951 if (FXM & (0x80 >> f))
2952 mask |= (0xf << 4*(7-f));
2954 CR = (MASKED(*rS, 32, 63) & mask) | (CR & ~mask);
2957 0.31,6.BF,9./,11./,16./,21.512,31./:X:::Move to Condition Register from XER
2959 0.31,6.RT,11./,16./,21.19,31./:X:::Move From Condition Register
2960 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2961 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
2962 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
2963 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
2964 *rT = (unsigned32)CR;
2967 # I.4.6.2 Floating-Point Load Instructions
2970 0.48,6.FRT,11.RA,16.D:D:f:lfs:Load Floating-Point Single
2971 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
2972 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2973 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2974 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2980 *frT = DOUBLE(MEM(unsigned, EA, 4));
2982 0.31,6.FRT,11.RA,16.RB,21.535,31./:X:f::Load Floating-Point Single Indexed
2983 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
2984 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2985 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2986 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2992 *frT = DOUBLE(MEM(unsigned, EA, 4));
2994 0.49,6.FRT,11.RA,16.D:D:f::Load Floating-Point Single with Update
2995 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
2996 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2997 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2998 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3001 program_interrupt(processor, cia,
3002 illegal_instruction_program_interrupt);
3004 *frT = DOUBLE(MEM(unsigned, EA, 4));
3007 0.31,6.FRT,11.RA,16.RB,21.576,31./:X:f::Load Floating-Point Single with Update Indexed
3008 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3009 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3010 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3011 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3014 program_interrupt(processor, cia,
3015 illegal_instruction_program_interrupt);
3017 *frT = DOUBLE(MEM(unsigned, EA, 4));
3020 0.50,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double
3021 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3022 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3023 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3024 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3030 *frT = MEM(unsigned, EA, 8);
3032 0.31,6.FRT,11.RA,16.RB,21.599,31./:X:f::Load Floating-Point Double Indexed
3033 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3034 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3035 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3036 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3042 *frT = MEM(unsigned, EA, 8);
3044 0.51,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double with Update
3045 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3046 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3047 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3048 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3051 program_interrupt(processor, cia,
3052 illegal_instruction_program_interrupt);
3054 *frT = MEM(unsigned, EA, 8);
3057 0.31,6.FRT,11.RA,16.RB,21.631,31./:X:f::Load Floating-Point Double with Update Indexed
3058 *601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3059 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3060 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3061 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3064 program_interrupt(processor, cia,
3065 illegal_instruction_program_interrupt);
3067 *frT = MEM(unsigned, EA, 8);
3072 # I.4.6.3 Floating-Point Store Instructions
3075 0.52,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single
3076 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3077 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3078 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3079 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3085 STORE(EA, 4, SINGLE(*frS));
3087 0.31,6.FRS,11.RA,16.RB,21.663,31./:X:f::Store Floating-Point Single Indexed
3088 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3089 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3090 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3091 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3097 STORE(EA, 4, SINGLE(*frS));
3099 0.53,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single with Update
3100 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3101 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3102 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3103 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3106 program_interrupt(processor, cia,
3107 illegal_instruction_program_interrupt);
3109 STORE(EA, 4, SINGLE(*frS));
3112 0.31,6.FRS,11.RA,16.RB,21.695,31./:X:f::Store Floating-Point Single with Update Indexed
3113 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3114 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3115 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3116 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3119 program_interrupt(processor, cia,
3120 illegal_instruction_program_interrupt);
3122 STORE(EA, 4, SINGLE(*frS));
3125 0.54,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double
3126 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3127 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3128 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3129 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3137 0.31,6.FRS,11.RA,16.RB,21.727,31./:X:f::Store Floating-Point Double Indexed
3138 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3139 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3140 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3141 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3149 0.55,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double with Update
3150 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3151 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3152 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3153 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3156 program_interrupt(processor, cia,
3157 illegal_instruction_program_interrupt);
3162 0.31,6.FRS,11.RA,16.RB,21.759,31./:X:f::Store Floating-Point Double with Update Indexed
3163 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3164 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3165 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3166 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3169 program_interrupt(processor, cia,
3170 illegal_instruction_program_interrupt);
3177 # I.4.6.4 Floating-Point Move Instructions
3180 0.63,6.FRT,11./,16.FRB,21.72,31.Rc:X:f::Floating Move Register
3181 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3182 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3183 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3184 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3188 0.63,6.FRT,11./,16.FRB,21.40,31.Rc:X:f::Floating Negate
3189 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3190 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3191 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3192 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3193 *frT = *frB ^ BIT64(0);
3196 0.63,6.FRT,11./,16.FRB,21.264,31.Rc:X:f::Floating Absolute Value
3197 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3198 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3199 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3200 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3201 *frT = *frB & ~BIT64(0);
3204 0.63,6.FRT,11./,16.FRB,21.136,31.Rc:X:f::Floating Negative Absolute Value
3205 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3206 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3207 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3208 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3209 *frT = *frB | BIT64(0);
3215 # I.4.6.5 Floating-Point Arithmetic Instructions
3218 0.63,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadd:Floating Add
3219 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3220 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3221 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3222 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3224 if (is_invalid_operation(processor, cia,
3226 fpscr_vxsnan | fpscr_vxisi,
3229 invalid_arithemetic_operation(processor, cia,
3231 0, /*instruction_is_frsp*/
3232 0, /*instruction_is_convert_to_64bit*/
3233 0, /*instruction_is_convert_to_32bit*/
3234 0); /*single-precision*/
3238 double s = *(double*)frA + *(double*)frB;
3243 0.59,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadds:Floating Add Single
3244 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3245 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3246 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3247 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3249 if (is_invalid_operation(processor, cia,
3251 fpscr_vxsnan | fpscr_vxisi,
3254 invalid_arithemetic_operation(processor, cia,
3256 0, /*instruction_is_frsp*/
3257 0, /*instruction_is_convert_to_64bit*/
3258 0, /*instruction_is_convert_to_32bit*/
3259 1); /*single-precision*/
3263 float s = *(double*)frA + *(double*)frB;
3268 0.63,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsub:Floating Subtract
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
3274 if (is_invalid_operation(processor, cia,
3276 fpscr_vxsnan | fpscr_vxisi,
3279 invalid_arithemetic_operation(processor, cia,
3281 0, /*instruction_is_frsp*/
3282 0, /*instruction_is_convert_to_64bit*/
3283 0, /*instruction_is_convert_to_32bit*/
3284 0); /*single-precision*/
3288 double s = *(double*)frA - *(double*)frB;
3293 0.59,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsubs:Floating Subtract Single
3294 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3295 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3296 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3297 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3299 if (is_invalid_operation(processor, cia,
3301 fpscr_vxsnan | fpscr_vxisi,
3304 invalid_arithemetic_operation(processor, cia,
3306 0, /*instruction_is_frsp*/
3307 0, /*instruction_is_convert_to_64bit*/
3308 0, /*instruction_is_convert_to_32bit*/
3309 1); /*single-precision*/
3313 float s = *(double*)frA - *(double*)frB;
3318 0.63,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmul:Floating Multiply
3319 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3320 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3321 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3322 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3324 if (is_invalid_operation(processor, cia,
3326 fpscr_vxsnan | fpscr_vximz,
3329 invalid_arithemetic_operation(processor, cia,
3331 0, /*instruction_is_frsp*/
3332 0, /*instruction_is_convert_to_64bit*/
3333 0, /*instruction_is_convert_to_32bit*/
3334 0); /*single-precision*/
3338 double s = *(double*)frA * *(double*)frC;
3343 0.59,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmuls:Floating Multiply Single
3344 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3345 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3346 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3347 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3349 if (is_invalid_operation(processor, cia,
3351 fpscr_vxsnan | fpscr_vximz,
3354 invalid_arithemetic_operation(processor, cia,
3356 0, /*instruction_is_frsp*/
3357 0, /*instruction_is_convert_to_64bit*/
3358 0, /*instruction_is_convert_to_32bit*/
3359 1); /*single-precision*/
3363 float s = *(double*)frA * *(double*)frC;
3368 0.63,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdiv:Floating Divide
3369 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 31, 31, 0
3370 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 33, 33, 0
3371 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 33, 33, 0
3372 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 32, 32, 0
3374 if (is_invalid_operation(processor, cia,
3376 fpscr_vxsnan | fpscr_vxzdz,
3379 invalid_arithemetic_operation(processor, cia,
3381 0, /*instruction_is_frsp*/
3382 0, /*instruction_is_convert_to_64bit*/
3383 0, /*instruction_is_convert_to_32bit*/
3384 0); /*single-precision*/
3388 double s = *(double*)frA / *(double*)frB;
3393 0.59,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdivs:Floating Divide Single
3394 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 17, 17, 0
3395 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0
3396 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0
3397 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0
3399 if (is_invalid_operation(processor, cia,
3401 fpscr_vxsnan | fpscr_vxzdz,
3404 invalid_arithemetic_operation(processor, cia,
3406 0, /*instruction_is_frsp*/
3407 0, /*instruction_is_convert_to_64bit*/
3408 0, /*instruction_is_convert_to_32bit*/
3409 1); /*single-precision*/
3413 float s = *(double*)frA / *(double*)frB;
3418 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f:fmadd:Floating Multiply-Add
3419 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3420 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3421 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3422 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3424 double product; /*HACK! - incorrectly loosing precision ... */
3425 /* compute the multiply */
3426 if (is_invalid_operation(processor, cia,
3428 fpscr_vxsnan | fpscr_vximz,
3431 invalid_arithemetic_operation(processor, cia,
3432 (unsigned64*)&product, *frA, 0, *frC,
3433 0, /*instruction_is_frsp*/
3434 0, /*instruction_is_convert_to_64bit*/
3435 0, /*instruction_is_convert_to_32bit*/
3436 0); /*single-precision*/
3440 product = *(double*)frA * *(double*)frC;
3442 /* compute the add */
3443 if (is_invalid_operation(processor, cia,
3445 fpscr_vxsnan | fpscr_vxisi,
3448 invalid_arithemetic_operation(processor, cia,
3449 frT, product, *frB, 0,
3450 0, /*instruction_is_frsp*/
3451 0, /*instruction_is_convert_to_64bit*/
3452 0, /*instruction_is_convert_to_32bit*/
3453 0); /*single-precision*/
3457 double s = product + *(double*)frB;
3462 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f::Floating Multiply-Add Single
3463 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3464 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3465 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3466 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3468 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract
3469 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3470 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3471 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3472 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3474 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract Single
3475 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3476 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3477 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3478 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3480 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add
3481 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3482 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3483 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3484 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3486 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add Single
3487 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3488 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3489 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3490 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3492 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract
3493 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3494 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3495 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3496 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3498 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract Single
3499 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3500 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3501 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3502 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3506 # I.4.6.6 Floating-Point Rounding and Conversion Instructions
3509 0.63,6.FRT,11./,16.FRB,21.12,31.Rc:X:f::Floating Round to Single-Precision
3510 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3511 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3512 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3513 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3516 unsigned64 frac_grx;
3517 /* split off cases for what to do */
3518 if (EXTRACTED64(*frB, 1, 11) < 897
3519 && EXTRACTED64(*frB, 1, 63) > 0) {
3520 if ((FPSCR & fpscr_ue) == 0) goto Disabled_Exponent_Underflow;
3521 if ((FPSCR & fpscr_ue) != 0) goto Enabled_Exponent_Underflow;
3523 if (EXTRACTED64(*frB, 1, 11) > 1150
3524 && EXTRACTED64(*frB, 1, 11) < 2047) {
3525 if ((FPSCR & fpscr_oe) == 0) goto Disabled_Exponent_Overflow;
3526 if ((FPSCR & fpscr_oe) != 0) goto Enabled_Exponent_Overflow;
3528 if (EXTRACTED64(*frB, 1, 11) > 896
3529 && EXTRACTED64(*frB, 1, 11) < 1151) goto Normal_Operand;
3530 if (EXTRACTED64(*frB, 1, 63) == 0) goto Zero_Operand;
3531 if (EXTRACTED64(*frB, 1, 11) == 2047) {
3532 if (EXTRACTED64(*frB, 12, 63) == 0) goto Infinity_Operand;
3533 if (EXTRACTED64(*frB, 12, 12) == 1) goto QNaN_Operand;
3534 if (EXTRACTED64(*frB, 12, 12) == 0
3535 && EXTRACTED64(*frB, 13, 63) > 0) goto SNaN_Operand;
3538 Disabled_Exponent_Underflow:
3539 sign = EXTRACTED64(*frB, 0, 0);
3540 if (EXTRACTED64(*frB, 1, 11) == 0) {
3542 frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
3544 if (EXTRACTED64(*frB, 1, 11) > 0) {
3545 exp = EXTRACTED64(*frB, 1, 11) - 1023;
3546 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
3548 Denormalize_Operand:
3549 /* G|R|X == zero from above */
3550 while (exp < -126) {
3552 frac_grx = (INSERTED64(EXTRACTED64(frac_grx, 0, 54), 1, 55)
3553 | MASKED64(frac_grx, 55, 55));
3555 FPSCR_SET_UX(EXTRACTED64(frac_grx, 24, 55) > 0);
3556 Round_Single(processor, sign, &exp, &frac_grx);
3557 FPSCR_SET_XX(FPSCR & fpscr_fi);
3558 if (EXTRACTED64(frac_grx, 0, 52) == 0) {
3559 *frT = INSERTED64(sign, 0, 0);
3560 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
3561 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
3563 if (EXTRACTED64(frac_grx, 0, 52) > 0) {
3564 if (EXTRACTED64(frac_grx, 0, 0) == 1) {
3565 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
3566 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
3568 if (EXTRACTED64(frac_grx, 0, 0) == 0) {
3569 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_denormalized_number);
3570 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_denormalized_number);
3572 /*Normalize_Operand:*/
3573 while (EXTRACTED64(frac_grx, 0, 0) == 0) {
3575 frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1, 52), 0, 51);
3577 *frT = (INSERTED64(sign, 0, 0)
3578 | INSERTED64(exp + 1023, 1, 11)
3579 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
3582 Enabled_Exponent_Underflow:
3584 sign = EXTRACTED64(*frB, 0, 0);
3585 if (EXTRACTED64(*frB, 1, 11) == 0) {
3587 frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
3589 if (EXTRACTED64(*frB, 1, 11) > 0) {
3590 exp = EXTRACTED64(*frB, 1, 11) - 1023;
3591 frac_grx = (BIT64(0) |
3592 INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52));
3594 /*Normalize_Operand:*/
3595 while (EXTRACTED64(frac_grx, 0, 0) == 0) {
3597 frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1, 52), 0, 51);
3599 Round_Single(processor, sign, &exp, &frac_grx);
3600 FPSCR_SET_XX(FPSCR & fpscr_fi);
3602 *frT = (INSERTED64(sign, 0, 0)
3603 | INSERTED64(exp + 1023, 1, 11)
3604 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
3605 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
3606 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
3608 Disabled_Exponent_Overflow:
3610 if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
3611 if (EXTRACTED64(*frB, 0, 0) == 0) {
3612 *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
3613 FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
3615 if (EXTRACTED64(*frB, 0, 0) == 1) {
3616 *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
3617 FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
3620 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_zero) {
3621 if (EXTRACTED64(*frB, 0, 0) == 0) {
3622 *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
3623 FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
3625 if (EXTRACTED64(*frB, 0, 0) == 1) {
3626 *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
3627 FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
3630 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_pos_infinity) {
3631 if (EXTRACTED64(*frB, 0, 0) == 0) {
3632 *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
3633 FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
3635 if (EXTRACTED64(*frB, 0, 0) == 1) {
3636 *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
3637 FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
3640 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_neg_infinity) {
3641 if (EXTRACTED64(*frB, 0, 0) == 0) {
3642 *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
3643 FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
3645 if (EXTRACTED64(*frB, 0, 0) == 1) {
3646 *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
3647 FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
3650 /* FPSCR[FR] <- undefined */
3654 Enabled_Exponent_Overflow:
3655 sign = EXTRACTED64(*frB, 0, 0);
3656 exp = EXTRACTED64(*frB, 1, 11) - 1023;
3657 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
3658 Round_Single(processor, sign, &exp, &frac_grx);
3659 FPSCR_SET_XX(FPSCR & fpscr_fi);
3663 *frT = (INSERTED64(sign, 0, 0)
3664 | INSERTED64(exp + 1023, 1, 11)
3665 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
3666 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
3667 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
3671 if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
3672 if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
3678 if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
3679 if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
3684 *frT = INSERTED64(EXTRACTED64(*frB, 0, 34), 0, 34);
3685 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
3690 FPSCR_OR_VX(fpscr_vxsnan);
3691 if ((FPSCR & fpscr_ve) == 0) {
3692 *frT = (MASKED64(*frB, 0, 11)
3694 | MASKED64(*frB, 13, 34));
3695 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
3701 sign = EXTRACTED64(*frB, 0, 0);
3702 exp = EXTRACTED64(*frB, 1, 11) - 1023;
3703 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
3704 Round_Single(processor, sign, &exp, &frac_grx);
3705 FPSCR_SET_XX(FPSCR & fpscr_fi);
3706 if (exp > 127 && (FPSCR & fpscr_oe) == 0) goto Disabled_Exponent_Overflow;
3707 if (exp > 127 && (FPSCR & fpscr_oe) != 0) goto Enabled_Overflow;
3708 *frT = (INSERTED64(sign, 0, 0)
3709 | INSERTED64(exp + 1023, 1, 11)
3710 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
3711 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
3712 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
3716 0.63,6.FRT,11./,16.FRB,21.814,31.Rc:X:64,f::Floating Convert To Integer Doubleword
3718 0.63,6.FRT,11./,16.FRB,21.815,31.Rc:X:64,f::Floating Convert To Integer Doubleword with round towards Zero
3720 0.63,6.FRT,11./,16.FRB,21.14,31.Rc:X:f::Floating Convert To Integer Word
3722 0.63,6.FRT,11./,16.FRB,21.15,31.Rc:X:f:fctiwz:Floating Convert To Integer Word with round towards Zero
3723 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3724 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3725 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3726 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3728 convert_to_integer(processor, cia,
3730 fpscr_rn_round_towards_zero, 32);
3733 0.63,6.FRT,11./,16.FRB,21.846,31.Rc:X:64,f::Floating Convert from Integer Doubleword
3734 int sign = EXTRACTED64(*frB, 0, 0);
3736 unsigned64 frac = *frB;
3737 if (frac == 0) goto Zero_Operand;
3738 if (sign == 1) frac = ~frac + 1;
3739 while (EXTRACTED64(frac, 0, 0) == 0) {
3740 /*??? do the loop 0 times if (FRB) = max negative integer */
3741 frac = INSERTED64(EXTRACTED64(frac, 1, 63), 0, 62);
3744 Round_Float(processor, sign, &exp, &frac, FPSCR & fpscr_rn);
3745 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
3746 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
3747 *frT = (INSERTED64(sign, 0, 0)
3748 | INSERTED64(exp + 1023, 1, 11)
3749 | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
3755 FPSCR_SET_FPRF(fpscr_rf_pos_zero);
3762 # I.4.6.7 Floating-Point Compare Instructions
3765 0.63,6.BF,9./,11.FRA,16.FRB,21.0,31./:X:f:fcmpu:Floating Compare Unordered
3766 *601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3767 *603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3768 *603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3769 *604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3772 if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
3773 c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
3774 else if (is_less_than(frA, frB))
3775 c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
3776 else if (is_greater_than(frA, frB))
3777 c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
3779 c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
3781 CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
3782 if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0))
3783 FPSCR_OR_VX(fpscr_vxsnan);
3786 0.63,6.BF,9./,11.FRA,16.FRB,21.32,31./:X:f:fcmpo:Floating Compare Ordered
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
3793 if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
3794 c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
3795 else if (is_less_than(frA, frB))
3796 c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
3797 else if (is_greater_than(frA, frB))
3798 c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
3800 c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
3802 CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
3803 if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0)) {
3804 FPSCR_OR_VX(fpscr_vxsnan);
3805 if ((FPSCR & fpscr_ve) == 0)
3806 FPSCR_OR_VX(fpscr_vxvc);
3808 else if (is_QNaN(*frA, 0) || is_QNaN(*frB, 0)) {
3809 FPSCR_OR_VX(fpscr_vxvc);
3815 # I.4.6.8 Floating-Point Status and Control Register Instructions
3818 0.63,6.FRT,11./,16./,21.583,31.Rc:X:f::Move From FPSCR
3820 0.63,6.BF,9./,11.BFA,14./,16./,21.64,31./:X:f::Move to Condition Register from FPSCR
3822 0.64,6.BF,9./,11./,16.U,20./,21.134,31.Rc:X:f::Move To FPSCR Field Immediate
3824 0.63,6./,7.FLM,15./,16.FRB,21.711,31.Rc:XFL:f::Move To FPSCR Fields
3826 0.63,6.BT,11./,16./,21.70,31.Rc:X:f::Move To FPSCR Bit 0
3828 0.63,6.BT,11./,16./,21.38,31.Rc:X:f::Move To FPSCR Bit 1
3832 # I.A.1.1 Floating-Point Store Instruction
3834 0.31,6.FRS,11.RA,16.RB,21.983,31./:X:f::Store Floating-Point as Integer Word Indexed
3837 # I.A.1.2 Floating-Point Arithmetic Instructions
3840 0.63,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f::Floating Square Root
3842 0.59,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f::Floating Square Root Single
3844 0.59,6.FRT,11./,16.FRB,21./,26.24,31.Rc:A:f::Floating Reciprocal Estimate Single
3846 0.63,6.FRT,11./,16.FRB,21./,26.26,31.Rc:A:f::Floating Reciprocal Square Root Estimate
3849 # I.A.1.3 Floating-Point Select Instruction
3852 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.23,31.Rc:A:f::Floating Select
3856 # II.3.2 Cache Management Instructions
3859 0.31,6./,11.RA,16.RB,21.982,31./:X::icbi:Instruction Cache Block Invalidate
3860 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3861 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3862 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3863 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
3864 /* blindly flush all instruction cache entries */
3865 #if WITH_IDECODE_CACHE_SIZE
3866 cpu_flush_icache(processor);
3869 0.19,6./,11./,16./,21.150,31./:XL::isync:Instruction Synchronize
3870 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3871 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3872 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3873 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
3874 cpu_synchronize_context(processor);
3878 # II.3.2.2 Data Cache Instructions
3881 0.31,6./,11.RA,16.RB,21.278,31./:X:::Data Cache Block Touch
3882 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3883 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
3884 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
3885 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
3886 TRACE(trace_tbd,("Data Cache Block Touch\n"));
3888 0.31,6./,11.RA,16.RB,21.246,31./:X:::Data Cache Block Touch for Store
3889 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3890 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
3891 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
3892 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3893 TRACE(trace_tbd,("Data Cache Block Touch for Store\n"));
3895 0.31,6./,11.RA,16.RB,21.1014,31./:X:::Data Cache Block set to Zero
3896 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3897 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 10, 10, 0
3898 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 10, 10, 0
3899 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3900 TRACE(trace_tbd,("Data Cache Block set to Zero\n"));
3902 0.31,6./,11.RA,16.RB,21.54,31./:X:::Data Cache Block Store
3903 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3904 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
3905 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
3906 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
3907 TRACE(trace_tbd,("Data Cache Block Store\n"));
3909 0.31,6./,11.RA,16.RB,21.86,31./:X:::Data Cache Block Flush
3910 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3911 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
3912 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
3913 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
3914 TRACE(trace_tbd,("Data Cache Block Flush\n"));
3917 # II.3.3 Enforce In-order Execution of I/O Instruction
3920 0.31,6./,11./,16./,21.854,31./:X::eieio:Enforce In-order Execution of I/O
3921 /* Since this model has no instruction overlap
3922 this instruction need do nothing */
3925 # II.4.1 Time Base Instructions
3928 0.31,6.RT,11.tbr,21.371,31./:XFX::mftb:Move From Time Base
3929 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3930 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3931 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
3932 int n = (tbr{5:9} << 5) | tbr{0:4};
3934 if (is_64bit_implementation) *rT = TB;
3935 else *rT = EXTRACTED64(TB, 32, 63);
3937 else if (n == 269) {
3938 if (is_64bit_implementation) *rT = EXTRACTED64(TB, 0, 31);
3939 else *rT = EXTRACTED64(TB, 0, 31);
3942 program_interrupt(processor, cia,
3943 illegal_instruction_program_interrupt);
3947 # III.2.3.1 System Linkage Instructions
3950 0.19,6./,11./,16./,21.50,31./:XL::rfi:Return From Interrupt
3951 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3952 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
3953 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
3954 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
3955 if (IS_PROBLEM_STATE(processor)) {
3956 program_interrupt(processor, cia,
3957 privileged_instruction_program_interrupt);
3960 MSR = (MASKED(SRR1, 0, 32)
3961 | MASKED(SRR1, 37, 41)
3962 | MASKED(SRR1, 48, 63));
3963 NIA = MASKED(SRR0, 0, 61);
3964 cpu_synchronize_context(processor);
3968 # III.3.4.1 Move to/from System Register Instructions
3971 #0.31,6.RS,11.spr,21.467,31./:XFX:::Move To Special Purpose Register
3972 #0.31,6.RT,11.spr,21.339,31./:XFX:::Move From Special Purpose Register
3973 0.31,6.RS,11./,16./,21.146,31./:X:::Move To Machine State Register
3974 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3975 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
3976 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
3977 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
3978 if (IS_PROBLEM_STATE(processor))
3979 program_interrupt(processor, cia,
3980 privileged_instruction_program_interrupt);
3984 0.31,6.RT,11./,16./,21.83,31./:X:::Move From Machine State Register
3985 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3986 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3987 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3988 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
3989 if (IS_PROBLEM_STATE(processor))
3990 program_interrupt(processor, cia,
3991 privileged_instruction_program_interrupt);
3997 # III.4.11.1 Cache Management Instructions
4000 0.31,6./,11.RA,16.RB,21.470,31./:X::dcbi:Data Cache Block Invalidate
4001 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4002 *603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4003 *603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4004 *604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4005 if (IS_PROBLEM_STATE(processor))
4006 program_interrupt(processor, cia,
4007 privileged_instruction_program_interrupt);
4009 TRACE(trace_tbd,("Data Cache Block Invalidate\n"));
4012 # III.4.11.2 Segment Register Manipulation Instructions
4015 0.31,6.RS,11./,12.SR,16./,21.210,31./:X:32:mtsr %SR,%RS:Move To Segment Register
4016 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4017 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4018 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4019 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4020 if (IS_PROBLEM_STATE(processor))
4021 program_interrupt(processor, cia,
4022 privileged_instruction_program_interrupt);
4026 0.31,6.RS,11./,16.RB,21.242,31./:X:32:mtsrin %RS,%RB:Move To Segment Register Indirect
4027 *601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4028 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4029 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4030 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4031 if (IS_PROBLEM_STATE(processor))
4032 program_interrupt(processor, cia,
4033 privileged_instruction_program_interrupt);
4035 SEGREG(EXTRACTED32(*rB, 0, 3)) = *rS;
4037 0.31,6.RT,11./,12.SR,16./,21.595,31./:X:32:mfsr %RT,%RS:Move From Segment Register
4038 *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
4039 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4040 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 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.RB,21.659,31./:X:32:mfsrin %RT,%RB:Move From Segment Register Indirect
4049 *601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
4050 *603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4051 *603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4052 *604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4053 if (IS_PROBLEM_STATE(processor))
4054 program_interrupt(processor, cia,
4055 privileged_instruction_program_interrupt);
4057 *rT = SEGREG(EXTRACTED32(*rB, 0, 3));
4061 # III.4.11.3 Lookaside Buffer Management Instructions (Optional)
4064 0.31,6./,11./,16.RB,21.434,31./:X:64::SLB Invalidate Entry
4066 0.31,6./,11./,16./,21.498,31./:X:64::SLB Invalidate All
4068 0.31,6./,11./,16.RB,21.306,31./:X:::TLB Invalidate Entry
4070 0.31,6./,11./,16./,21.370,31./:X:::TLB Invalidate All
4072 0.31,6./,11./,16./,21.566,31./:X:::TLB Sychronize
4076 # III.A.1.2 External Access Instructions
4079 0.31,6.RT,11.RA,16.RB,21.310,31./:X:earwax::External Control In Word Indexed
4081 0.31,6.RS,11.RA,16.RB,21.438,31./:X:earwax::External Control Out Word Indexed