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