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