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