import gdb-1999-10-18 snapshot
[deliverable/binutils-gdb.git] / sim / ppc / ppc-instructions
CommitLineData
c906108c
SS
1#
2# This file is part of the program psim.
3#
4# Copyright (C) 1994-1997, 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\f
37# PowerPC models
38::model:604:ppc604: PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0
39::model:603e:ppc603e:PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0
40::model:603:ppc603: PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0
41::model:601:ppc601: PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0
42
43# Flags for model.h
44::model-macro:::
45 #define PPC_INSN_INT(OUT_MASK, IN_MASK, RC) \
46 do { \
47 if (CURRENT_MODEL_ISSUE > 0) { \
48 if (RC) \
49 ppc_insn_int_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, 1 << 0); \
50 else \
51 ppc_insn_int(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK); \
52 } \
53 } while (0)
54
55 #define PPC_INSN_INT_CR(OUT_MASK, IN_MASK, CR_MASK) \
56 do { \
57 if (CURRENT_MODEL_ISSUE > 0) \
58 ppc_insn_int_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, CR_MASK); \
59 } while (0)
60
61 #define PPC_INSN_CR(OUT_MASK, IN_MASK) \
62 do { \
63 if (CURRENT_MODEL_ISSUE > 0) \
64 ppc_insn_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK); \
65 } while (0)
66
67 #define PPC_INSN_FLOAT(OUT_MASK, IN_MASK, RC) \
68 do { \
69 if (CURRENT_MODEL_ISSUE > 0) { \
70 if (RC) \
71 ppc_insn_float(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK); \
72 else \
73 ppc_insn_float_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, 1 << 0); \
74 } \
75 } while (0)
76
77 #define PPC_INSN_FLOAT_CR(OUT_MASK, IN_MASK, CR_MASK) \
78 do { \
79 if (CURRENT_MODEL_ISSUE > 0) \
80 ppc_insn_float_cr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, CR_MASK); \
81 } while (0)
82
83 #define PPC_INSN_INT_FLOAT(OUT_INT_MASK, OUT_FP_MASK, IN_INT_MASK, IN_FP_MASK) \
84 do { \
85 if (CURRENT_MODEL_ISSUE > 0) \
86 ppc_insn_int_float(MY_INDEX, cpu_model(processor), OUT_INT_MASK, OUT_FP_MASK, IN_INT_MASK, IN_FP_MASK); \
87 } while (0)
88
89 #define PPC_INSN_FROM_SPR(INT_MASK, SPR) \
90 do { \
91 if (CURRENT_MODEL_ISSUE > 0) \
92 ppc_insn_from_spr(MY_INDEX, cpu_model(processor), INT_MASK, SPR); \
93 } while (0)
94
95 #define PPC_INSN_TO_SPR(INT_MASK, SPR) \
96 do { \
97 if (CURRENT_MODEL_ISSUE > 0) \
98 ppc_insn_to_spr(MY_INDEX, cpu_model(processor), INT_MASK, SPR); \
99 } while (0)
100
101 #define PPC_INSN_MFCR(INT_MASK) \
102 do { \
103 if (CURRENT_MODEL_ISSUE > 0) \
104 ppc_insn_mfcr(MY_INDEX, cpu_model(processor), INT_MASK); \
105 } while (0)
106
107 #define PPC_INSN_MTCR(INT_MASK, FXM) \
108 do { \
109 if (CURRENT_MODEL_ISSUE > 0) \
110 ppc_insn_mtcr(MY_INDEX, cpu_model(processor), INT_MASK, FXM); \
111 } while (0)
112
113::model-data:::
114 typedef enum _ppc_function_unit {
115 PPC_UNIT_BAD, /* unknown function unit */
116 PPC_UNIT_IU, /* integer unit (601/603 style) */
117 PPC_UNIT_SRU, /* system register unit (601/603 style) */
118 PPC_UNIT_SCIU1, /* 1st single cycle integer unit (604 style) */
119 PPC_UNIT_SCIU2, /* 2nd single cycle integer unit (604 style) */
120 PPC_UNIT_MCIU, /* multiple cycle integer unit (604 style) */
121 PPC_UNIT_FPU, /* floating point unit */
122 PPC_UNIT_LSU, /* load/store unit */
123 PPC_UNIT_BPU, /* branch unit */
124 nr_ppc_function_units
125 } ppc_function_unit;
126
127 /* Structure to hold timing information on a per instruction basis */
128 struct _model_time {
129 ppc_function_unit first_unit; /* first functional unit this insn could use */
130 ppc_function_unit second_unit; /* second functional unit this insn could use */
131 signed16 issue; /* # cycles before function unit can process other insns */
132 signed16 done; /* # cycles before insn is done */
133 unsigned32 flags; /* any flags that are needed */
134 };
135
136 /* Register mappings in status masks */
137 #define PPC_CR_REG 0 /* start of CR0 .. CR7 */
138 #define PPC_FPSCR_REG (PPC_CR_REG + 8) /* start of fpscr register */
139
140 #define PPC_NO_SPR (-1) /* flag for no SPR register */
141
142 /* Return if 1 bit set */
143 #define PPC_ONE_BIT_SET_P(x) (((x) & ((x)-1)) == 0)
144
145 /* Structure for each functional unit that is busy */
146 typedef struct _model_busy model_busy;
147 struct _model_busy {
148 model_busy *next; /* next function unit */
149 ppc_function_unit unit; /* function unit name */
150 unsigned32 int_busy; /* int registers that are busy */
151 unsigned32 fp_busy; /* floating point registers that are busy */
152 unsigned32 cr_fpscr_busy; /* CR/FPSCR registers that are busy */
153 signed16 spr_busy; /* SPR register that is busy or PPC_NO_SPR */
154 signed16 issue; /* # of cycles until unit can accept another insn */
155 signed16 done; /* # of cycles until insn is done */
156 signed16 nr_writebacks; /* # of registers this unit writes back */
157 };
158
159 /* Structure to hold the current state information for the simulated CPU model */
160 struct _model_data {
161 cpu *processor; /* point back to processor */
162 const char *name; /* model name */
163 const model_time *timing; /* timing information */
164 model_busy busy_head; /* dummy entry to head list of busy function units */
165 model_busy *busy_tail; /* tail of list of busy function units */
166 model_busy *free_list; /* list of model_busy structs not in use */
167 count_type nr_cycles; /* # cycles */
168 count_type nr_branches; /* # branches */
169 count_type nr_branches_fallthrough; /* # conditional branches that fell through */
170 count_type nr_branch_predict_trues; /* # branches predicted correctly */
171 count_type nr_branch_predict_falses; /* # branches predicted incorrectly */
172 count_type nr_branch_conditional[32]; /* # of each type of bc */
173 count_type nr_mtcrf_crs[9]; /* # of CR's moved in a mtcrf instruction */
174 count_type nr_stalls_data; /* # of stalls for data */
175 count_type nr_stalls_unit; /* # of stalls waiting for a function unit */
176 count_type nr_stalls_serialize; /* # of stalls waiting for things to quiet down */
177 count_type nr_stalls_writeback; /* # of stalls waiting for a writeback slot */
178 count_type nr_units[nr_ppc_function_units]; /* function unit counts */
179 int max_nr_writebacks; /* max # of writeback slots available */
180 unsigned32 int_busy; /* int registers that are busy */
181 unsigned32 fp_busy; /* floating point registers that are busy */
182 unsigned32 cr_fpscr_busy; /* CR/FPSCR registers that are busy */
183 unsigned8 spr_busy[nr_of_sprs]; /* SPR registers that are busy */
184 unsigned8 busy[nr_ppc_function_units]; /* whether a function is busy or not */
185 };
186
187 static const char *const ppc_function_unit_name[ (int)nr_ppc_function_units ] = {
188 "unknown functional unit instruction",
189 "integer functional unit instruction",
190 "system register functional unit instruction",
191 "1st single cycle integer functional unit instruction",
192 "2nd single cycle integer functional unit instruction",
193 "multiple cycle integer functional unit instruction",
194 "floating point functional unit instruction",
195 "load/store functional unit instruction",
196 "branch functional unit instruction",
197 };
198
199 static const char *const ppc_branch_conditional_name[32] = {
200 "branch if --CTR != 0 and condition is FALSE", /* 0000y */
201 "branch if --CTR != 0 and condition is FALSE, reverse branch likely",
202 "branch if --CTR == 0 and condition is FALSE", /* 0001y */
203 "branch if --CTR == 0 and condition is FALSE, reverse branch likely",
204 "branch if the condition is FALSE", /* 001zy */
205 "branch if the condition is FALSE, reverse branch likely",
206 "branch if the condition is FALSE (ignored bit 1 set to 1)", /* 001zy */
207 "branch if the condition is FALSE, reverse branch likely (ignored bit 4 set to 1)",
208 "branch if --CTR != 0 and condition is TRUE", /* 0100y */
209 "branch if --CTR != 0 and condition is TRUE, reverse branch likely",
210 "branch if --CTR == 0 and condition is TRUE", /* 0101y */
211 "branch if --CTR == 0 and condition is TRUE, reverse branch likely",
212 "branch if the condition is TRUE", /* 011zy */
213 "branch if the condition is TRUE, reverse branch likely",
214 "branch if the condition is TRUE (ignored bit 1 set to 1)", /* 011zy */
215 "branch if the condition is TRUE, reverse branch likely (ignored bit 4 set to 1)",
216 "branch if --CTR != 0", /* 1z00y */
217 "branch if --CTR != 0, reverse branch likely",
218 "branch if --CTR == 0", /* 1z01y */
219 "branch if --CTR == 0, reverse branch likely",
220 "branch always", /* 1z1zz */
221 "branch always (ignored bit 5 set to 1)",
222 "branch always (ignored bit 4 set to 1)", /* 1z1zz */
223 "branch always (ignored bits 4,5 set to 1)",
224 "branch if --CTR != 0 (ignored bit 1 set to 1)", /* 1z00y */
225 "branch if --CTR != 0, reverse branch likely (ignored bit 1 set to 1)",
226 "branch if --CTR == 0 (ignored bit 1 set to 1)", /* 1z01y */
227 "branch if --CTR == 0, reverse branch likely (ignored bit 1 set to 1)",
228 "branch always (ignored bit 1 set to 1)", /* 1z1zz */
229 "branch always (ignored bits 1,5 set to 1)",
230 "branch always (ignored bits 1,4 set to 1)", /* 1z1zz */
231 "branch always (ignored bits 1,4,5 set to 1)",
232 };
233
234 static const char *const ppc_nr_mtcrf_crs[9] = {
235 "mtcrf moving 0 CRs",
236 "mtcrf moving 1 CR",
237 "mtcrf moving 2 CRs",
238 "mtcrf moving 3 CRs",
239 "mtcrf moving 4 CRs",
240 "mtcrf moving 5 CRs",
241 "mtcrf moving 6 CRs",
242 "mtcrf moving 7 CRs",
243 "mtcrf moving all CRs",
244 };
245\f
246# Trace releasing resources
247void::model-static::model_trace_release:model_data *model_ptr, model_busy *busy
248 int i;
249 TRACE(trace_model,("done, %s, %d writeback%s\n", ppc_function_unit_name[busy->unit],
250 busy->nr_writebacks, busy->nr_writebacks == 1 ? "" : "s"));
251 if (busy->int_busy) {
252 for(i = 0; i < 32; i++) {
253 if (((1 << i) & busy->int_busy) != 0) {
254 TRACE(trace_model, ("Register r%d is now available.\n", i));
255 }
256 }
257 }
258 if (busy->fp_busy) {
259 for(i = 0; i < 32; i++) {
260 if (((1 << i) & busy->fp_busy) != 0) {
261 TRACE(trace_model, ("Register f%d is now available.\n", i));
262 }
263 }
264 }
265 if (busy->cr_fpscr_busy) {
266 for(i = 0; i < 8; i++) {
267 if (((1 << i) & busy->cr_fpscr_busy) != 0) {
268 TRACE(trace_model, ("Register cr%d is now available.\n", i));
269 }
270 }
271 if (busy->cr_fpscr_busy & 0x100)
272 TRACE(trace_model, ("Register fpscr is now available.\n"));
273 }
274 if (busy->spr_busy != PPC_NO_SPR)
275 TRACE(trace_model, ("Register %s is now available.\n", spr_name(busy->spr_busy)));
276
277# Trace making registers busy
278void::model-static::model_trace_make_busy:model_data *model_ptr, unsigned32 int_mask, unsigned32 fp_mask, unsigned32 cr_mask
279 int i;
280 if (int_mask) {
281 for(i = 0; i < 32; i++) {
282 if (((1 << i) & int_mask) != 0) {
283 TRACE(trace_model, ("Register r%d is now busy.\n", i));
284 }
285 }
286 }
287 if (fp_mask) {
288 for(i = 0; i < 32; i++) {
289 if (((1 << i) & fp_mask) != 0) {
290 TRACE(trace_model, ("Register f%d is now busy.\n", i));
291 }
292 }
293 }
294 if (cr_mask) {
295 for(i = 0; i < 8; i++) {
296 if (((1 << i) & cr_mask) != 0) {
297 TRACE(trace_model, ("Register cr%d is now busy.\n", i));
298 }
299 }
300 }
301
302# Trace waiting for registers to become available
303void::model-static::model_trace_busy_p:model_data *model_ptr, unsigned32 int_busy, unsigned32 fp_busy, unsigned32 cr_or_fpscr_busy, int spr_busy
304 int i;
305 if (int_busy) {
306 int_busy &= model_ptr->int_busy;
307 for(i = 0; i < 32; i++) {
308 if (((1 << i) & int_busy) != 0) {
309 TRACE(trace_model, ("Waiting for register r%d.\n", i));
310 }
311 }
312 }
313 if (fp_busy) {
314 fp_busy &= model_ptr->fp_busy;
315 for(i = 0; i < 32; i++) {
316 if (((1 << i) & fp_busy) != 0) {
317 TRACE(trace_model, ("Waiting for register f%d.\n", i));
318 }
319 }
320 }
321 if (cr_or_fpscr_busy) {
322 cr_or_fpscr_busy &= model_ptr->cr_fpscr_busy;
323 for(i = 0; i < 8; i++) {
324 if (((1 << i) & cr_or_fpscr_busy) != 0) {
325 TRACE(trace_model, ("Waiting for register cr%d.\n", i));
326 }
327 }
328 if (cr_or_fpscr_busy & 0x100)
329 TRACE(trace_model, ("Waiting for register fpscr.\n"));
330 }
331 if (spr_busy != PPC_NO_SPR && model_ptr->spr_busy[spr_busy])
332 TRACE(trace_model, ("Waiting for register %s.\n", spr_name(spr_busy)));
333\f
334# Advance state to next cycle, releasing any registers allocated
335void::model-internal::model_new_cycle:model_data *model_ptr
336 model_busy *cur_busy = model_ptr->busy_head.next;
337 model_busy *free_list = model_ptr->free_list;
338 model_busy *busy_tail = &model_ptr->busy_head;
339 int nr_writebacks = model_ptr->max_nr_writebacks;
340 model_busy *next;
341
342 model_ptr->nr_cycles++;
343 TRACE(trace_model,("New cycle %lu\n", (unsigned long)model_ptr->nr_cycles));
344 for ( ; cur_busy; cur_busy = next) {
345 next = cur_busy->next;
346 if (--cur_busy->done <= 0) { /* function unit done, release registers if we have writeback slots */
347 nr_writebacks -= cur_busy->nr_writebacks;
348 if (nr_writebacks >= 0) {
349 model_ptr->int_busy &= ~cur_busy->int_busy;
350 model_ptr->fp_busy &= ~cur_busy->fp_busy;
351 model_ptr->cr_fpscr_busy &= ~cur_busy->cr_fpscr_busy;
352 if (cur_busy->spr_busy != PPC_NO_SPR)
353 model_ptr->spr_busy[cur_busy->spr_busy] = 0;
354
355 if (WITH_TRACE && ppc_trace[trace_model])
356 model_trace_release(model_ptr, cur_busy);
357
358 model_ptr->busy[cur_busy->unit] = 0;
359 cur_busy->next = free_list;
360 free_list = cur_busy;
361 }
362 else { /* writeback slots not available */
363 TRACE(trace_model,("%d writeback slot%s not available for %s\n",
364 cur_busy->nr_writebacks,
365 cur_busy->nr_writebacks == 1 ? " is" : "s are",
366 ppc_function_unit_name[cur_busy->unit]));
367 cur_busy->done++; /* undo -- above */
368 model_ptr->nr_stalls_writeback++;
369 busy_tail->next = cur_busy;
370 busy_tail = cur_busy;
371 }
372 }
373 else if (--cur_busy->issue <= 0) { /* function unit pipelined, allow new use */
374 TRACE(trace_model,("pipeline, %s ready for next client\n", ppc_function_unit_name[cur_busy->unit]));
375 model_ptr->busy[cur_busy->unit] = 0;
376 busy_tail->next = cur_busy;
377 busy_tail = cur_busy;
378 }
379 else {
380 TRACE(trace_model,("%s still working, issue = %d, done = %d\n",
381 ppc_function_unit_name[cur_busy->unit],
382 cur_busy->issue,
383 cur_busy->done));
384 busy_tail->next = cur_busy;
385 busy_tail = cur_busy;
386 }
387 }
388
389 busy_tail->next = (model_busy *)0;
390 model_ptr->busy_tail = busy_tail;
391 model_ptr->free_list = free_list;
392
393# Mark a function unit as busy, return the busy structure
394model_busy *::model-internal::model_make_busy:model_data *model_ptr, ppc_function_unit unit, int issue, int done
395 model_busy *busy;
396
397 TRACE(trace_model,("unit = %s, issue = %d, done = %d\n", ppc_function_unit_name[unit], issue, done));
398
399 if (!model_ptr->free_list) {
400 busy = ZALLOC(model_busy);
401 }
402 else {
403 busy = model_ptr->free_list;
404 model_ptr->free_list = busy->next;
405 busy->next = (model_busy *)0;
406 busy->int_busy = 0;
407 busy->fp_busy = 0;
408 busy->cr_fpscr_busy = 0;
409 busy->nr_writebacks = 0;
410 }
411
412 busy->unit = unit;
413 busy->issue = issue;
414 busy->done = done;
415 busy->spr_busy = PPC_NO_SPR;
416 model_ptr->busy_tail->next = busy;
417 model_ptr->busy_tail = busy;
418 model_ptr->busy[unit] = 1;
419 model_ptr->nr_units[unit]++;
420 return busy;
421\f
422# Wait until a function unit is non-busy, and then allocate a busy pointer & return the pointer
423model_busy *::model-internal::model_wait_for_unit:itable_index index, model_data *const model_ptr, const model_time *const time_ptr
424 ppc_function_unit first_unit = time_ptr->first_unit;
425 ppc_function_unit second_unit = time_ptr->second_unit;
426 int stall_increment = 0;
427
428 for (;;) {
429 if (!model_ptr->busy[first_unit])
430 return model_make_busy(model_ptr, first_unit,
431 model_ptr->timing[index].issue,
432 model_ptr->timing[index].done);
433
434 if (!model_ptr->busy[second_unit])
435 return model_make_busy(model_ptr, second_unit,
436 model_ptr->timing[index].issue,
437 model_ptr->timing[index].done);
438
439 TRACE(trace_model,("all function units are busy for %s\n", itable[index].name));
440 model_ptr->nr_stalls_unit += stall_increment; /* don't count first stall */
441 stall_increment = 1;
442 model_new_cycle(model_ptr);
443 }
444
445# Serialize the processor, waiting for all instructions to drain out before adding an instruction.
446void::model-function::model_serialize:itable_index index, model_data *model_ptr
447 while (model_ptr->busy_head.next) {
448 TRACE(trace_model,("waiting for pipeline to empty\n"));
449 model_ptr->nr_stalls_serialize++;
450 model_new_cycle(model_ptr);
451 }
452 (void) model_make_busy(model_ptr,
453 model_ptr->timing[index].first_unit,
454 model_ptr->timing[index].issue,
455 model_ptr->timing[index].done);
456
457# Wait for a CR to become unbusy
458void::model-function::model_wait_for_cr:model_data *model_ptr, unsigned CRBIT
459 unsigned u;
460 unsigned32 cr_mask;
461 int cr_var = 0;
462 for (u = 0xc0000000; (u != 0) && (CRBIT & u) == 0; u >>= 4 )
463 cr_var++;
464
465 cr_mask = (1 << cr_var);
466 while ((model_ptr->cr_fpscr_busy & cr_mask) != 0) {
467 TRACE(trace_model,("waiting for CR %d\n", cr_var));
468 model_ptr->nr_stalls_data++;
469 model_new_cycle(model_ptr);
470 }
471
472# Schedule an instruction that takes integer input registers and produces output registers
473void::model-function::ppc_insn_int:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask
474 const unsigned32 int_mask = out_mask | in_mask;
475 model_busy *busy_ptr;
476
477 if ((model_ptr->int_busy & int_mask) != 0) {
478 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
479
480 while ((model_ptr->int_busy & int_mask) != 0) {
481 if (WITH_TRACE && ppc_trace[trace_model])
482 model_trace_busy_p(model_ptr, int_mask, 0, 0, PPC_NO_SPR);
483
484 model_ptr->nr_stalls_data++;
485 model_new_cycle(model_ptr);
486 }
487 }
488
489 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
490 model_ptr->int_busy |= out_mask;
491 busy_ptr->int_busy |= out_mask;
492 if (out_mask)
493 busy_ptr->nr_writebacks = (PPC_ONE_BIT_SET_P(out_mask)) ? 1 : 2;
494
495 if (WITH_TRACE && ppc_trace[trace_model])
496 model_trace_make_busy(model_ptr, out_mask, 0, 0);
497
498# Schedule an instruction that takes integer input registers and produces output registers & sets a CR register
499void::model-function::ppc_insn_int_cr:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask, const unsigned32 cr_mask
500 const unsigned32 int_mask = out_mask | in_mask;
501 model_busy *busy_ptr;
502
503 if ((model_ptr->int_busy & int_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
504 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
505
506 while ((model_ptr->int_busy & int_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
507 if (WITH_TRACE && ppc_trace[trace_model])
508 model_trace_busy_p(model_ptr, int_mask, 0, cr_mask, PPC_NO_SPR);
509
510 model_ptr->nr_stalls_data++;
511 model_new_cycle(model_ptr);
512 }
513 }
514
515 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
516 model_ptr->int_busy |= out_mask;
517 busy_ptr->int_busy |= out_mask;
518 model_ptr->cr_fpscr_busy |= cr_mask;
519 busy_ptr->cr_fpscr_busy |= cr_mask;
520 if (out_mask)
521 busy_ptr->nr_writebacks = (PPC_ONE_BIT_SET_P(out_mask)) ? 1 : 2;
522
523 if (cr_mask)
524 busy_ptr->nr_writebacks++;
525
526 if (WITH_TRACE && ppc_trace[trace_model])
527 model_trace_make_busy(model_ptr, out_mask, 0, cr_mask);
528
529
530# Schedule an instruction that takes CR input registers and produces output CR registers
531void::model-function::ppc_insn_cr:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask
532 const unsigned32 cr_mask = out_mask | in_mask;
533 model_busy *busy_ptr;
534
535 if ((model_ptr->cr_fpscr_busy & cr_mask) != 0) {
536 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
537
538 while ((model_ptr->cr_fpscr_busy & cr_mask) != 0) {
539 if (WITH_TRACE && ppc_trace[trace_model])
540 model_trace_busy_p(model_ptr, 0, 0, cr_mask, PPC_NO_SPR);
541
542 model_ptr->nr_stalls_data++;
543 model_new_cycle(model_ptr);
544 }
545 }
546
547 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
548 model_ptr->cr_fpscr_busy |= out_mask;
549 busy_ptr->cr_fpscr_busy |= out_mask;
550 if (out_mask)
551 busy_ptr->nr_writebacks = 1;
552
553 if (WITH_TRACE && ppc_trace[trace_model])
554 model_trace_make_busy(model_ptr, 0, 0, out_mask);
555
556
557# Schedule an instruction that takes floating point input registers and produces an output fp register
558void::model-function::ppc_insn_float:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask
559 const unsigned32 fp_mask = out_mask | in_mask;
560 model_busy *busy_ptr;
561
562 if ((model_ptr->fp_busy & fp_mask) != 0) {
563 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
564
565 while ((model_ptr->fp_busy & fp_mask) != 0) {
566 if (WITH_TRACE && ppc_trace[trace_model])
567 model_trace_busy_p(model_ptr, 0, fp_mask, 0, PPC_NO_SPR);
568
569 model_ptr->nr_stalls_data++;
570 model_new_cycle(model_ptr);
571 }
572 }
573
574 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
575 model_ptr->fp_busy |= out_mask;
576 busy_ptr->fp_busy |= out_mask;
577 busy_ptr->nr_writebacks = 1;
578 if (WITH_TRACE && ppc_trace[trace_model])
579 model_trace_make_busy(model_ptr, 0, out_mask, 0);
580
581
582# Schedule an instruction that takes floating point input registers and produces an output fp register & sets a CR reg
583void::model-function::ppc_insn_float_cr:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask, const unsigned32 cr_mask
584 const unsigned32 fp_mask = out_mask | in_mask;
585 model_busy *busy_ptr;
586
587 if ((model_ptr->fp_busy & fp_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
588 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
589
590 while ((model_ptr->fp_busy & fp_mask) || (model_ptr->cr_fpscr_busy & cr_mask)) {
591 if (WITH_TRACE && ppc_trace[trace_model])
592 model_trace_busy_p(model_ptr, 0, fp_mask, cr_mask, PPC_NO_SPR);
593
594 model_ptr->nr_stalls_data++;
595 model_new_cycle(model_ptr);
596 }
597 }
598
599 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
600 model_ptr->fp_busy |= out_mask;
601 busy_ptr->fp_busy |= out_mask;
602 model_ptr->cr_fpscr_busy |= cr_mask;
603 busy_ptr->cr_fpscr_busy |= cr_mask;
604 busy_ptr->nr_writebacks = (cr_mask) ? 2 : 1;
605 if (WITH_TRACE && ppc_trace[trace_model])
606 model_trace_make_busy(model_ptr, 0, out_mask, cr_mask);
607
608
609# Schedule an instruction that takes both int/float input registers and produces output int/float registers
610void::model-function::ppc_insn_int_float:itable_index index, model_data *model_ptr, const unsigned32 out_int_mask, const unsigned32 out_fp_mask, const unsigned32 in_int_mask, const unsigned32 in_fp_mask
611 const unsigned32 int_mask = out_int_mask | in_int_mask;
612 const unsigned32 fp_mask = out_fp_mask | in_fp_mask;
613 model_busy *busy_ptr;
614
615 if ((model_ptr->int_busy & int_mask) || (model_ptr->fp_busy & fp_mask)) {
616 model_new_cycle(model_ptr); /* don't count first dependency as a stall */
617
618 while ((model_ptr->int_busy & int_mask) || (model_ptr->fp_busy & fp_mask)) {
619 if (WITH_TRACE && ppc_trace[trace_model])
620 model_trace_busy_p(model_ptr, int_mask, fp_mask, 0, PPC_NO_SPR);
621
622 model_ptr->nr_stalls_data++;
623 model_new_cycle(model_ptr);
624 }
625
626 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
627 model_ptr->int_busy |= out_int_mask;
628 busy_ptr->int_busy |= out_int_mask;
629 model_ptr->fp_busy |= out_fp_mask;
630 busy_ptr->fp_busy |= out_fp_mask;
631 busy_ptr->nr_writebacks = ((out_int_mask) ? 1 : 0) + ((out_fp_mask) ? 1 : 0);
632 if (WITH_TRACE && ppc_trace[trace_model])
633 model_trace_make_busy(model_ptr, out_int_mask, out_fp_mask, 0);
634 return;
635 }
636
637# Schedule an MFSPR instruction that takes 1 special purpose register and produces an integer output register
638void::model-function::ppc_insn_from_spr:itable_index index, model_data *model_ptr, const unsigned32 int_mask, const unsigned nSPR
639 model_busy *busy_ptr;
640
641 while ((model_ptr->int_busy & int_mask) != 0 || model_ptr->spr_busy[nSPR] != 0) {
642 if (WITH_TRACE && ppc_trace[trace_model])
643 model_trace_busy_p(model_ptr, int_mask, 0, 0, nSPR);
644
645 model_ptr->nr_stalls_data++;
646 model_new_cycle(model_ptr);
647 }
648
649 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
650 model_ptr->int_busy |= int_mask;
651 busy_ptr->int_busy |= int_mask;
652 busy_ptr->nr_writebacks = 1;
653 if (WITH_TRACE && ppc_trace[trace_model])
654 model_trace_make_busy(model_ptr, int_mask, 0, 0);
655
656# Schedule an MTSPR instruction that takes 1 integer register and produces a special purpose output register
657void::model-function::ppc_insn_to_spr:itable_index index, model_data *model_ptr, const unsigned32 int_mask, const unsigned nSPR
658 model_busy *busy_ptr;
659
660 while ((model_ptr->int_busy & int_mask) != 0 || model_ptr->spr_busy[nSPR] != 0) {
661 if (WITH_TRACE && ppc_trace[trace_model])
662 model_trace_busy_p(model_ptr, int_mask, 0, 0, nSPR);
663
664 model_ptr->nr_stalls_data++;
665 model_new_cycle(model_ptr);
666 }
667
668 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
669 busy_ptr->spr_busy = nSPR;
670 model_ptr->spr_busy[nSPR] = 1;
671 busy_ptr->nr_writebacks = 1;
672 TRACE(trace_model,("Making register %s busy.\n", spr_name(nSPR)));
673
674# Schedule a MFCR instruction that moves the CR into an integer regsiter
675void::model-function::ppc_insn_mfcr:itable_index index, model_data *model_ptr, unsigned32 int_mask
676 const unsigned32 cr_mask = 0xff;
677 model_busy *busy_ptr;
678
679 while (((model_ptr->int_busy & int_mask) | (model_ptr->cr_fpscr_busy & cr_mask)) != 0) {
680 if (WITH_TRACE && ppc_trace[trace_model])
681 model_trace_busy_p(model_ptr, int_mask, 0, cr_mask, PPC_NO_SPR);
682
683 model_ptr->nr_stalls_data++;
684 model_new_cycle(model_ptr);
685 }
686
687 busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
688 model_ptr->int_busy |= int_mask;
689 busy_ptr->int_busy |= int_mask;
690 busy_ptr->nr_writebacks = 1;
691 if (WITH_TRACE && ppc_trace[trace_model])
692 model_trace_make_busy(model_ptr, int_mask, 0, 0);
693
694# Schedule a MTCR instruction that moves an integer register into the CR
695void::model-function::ppc_insn_mtcr:itable_index index, model_data *model_ptr, unsigned32 int_mask, unsigned FXM
696 int f;
697 int nr_crs = 0;
698 unsigned32 cr_mask = 0;
699 const model_time *normal_time = &model_ptr->timing[index];
700 static const model_time ppc604_1bit_time = { PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0 };
701 model_busy *busy_ptr;
702
703 for (f = 0; f < 8; f++) {
704 if (FXM & (0x80 >> f)) {
705 cr_mask |= (1 << f);
706 nr_crs++;
707 }
708 }
709
710 while (((model_ptr->int_busy & int_mask) | (model_ptr->cr_fpscr_busy & cr_mask)) != 0) {
711 if (WITH_TRACE && ppc_trace[trace_model])
712 model_trace_busy_p(model_ptr, int_mask, 0, cr_mask, PPC_NO_SPR);
713
714 model_ptr->nr_stalls_data++;
715 model_new_cycle(model_ptr);
716 }
717
718 /* If only one CR is being moved, use the SCIU, not the MCIU on the 604 */
719 if (CURRENT_MODEL == MODEL_ppc604 && nr_crs == 1) {
720 normal_time = &ppc604_1bit_time;
721 }
722
723 busy_ptr = model_wait_for_unit(index, model_ptr, normal_time);
724 busy_ptr->cr_fpscr_busy |= cr_mask;
725 model_ptr->cr_fpscr_busy |= cr_mask;
726 model_ptr->nr_mtcrf_crs[nr_crs]++;
727 busy_ptr->nr_writebacks = 1;
728 if (WITH_TRACE && ppc_trace[trace_model])
729 model_trace_make_busy(model_ptr, 0, 0, cr_mask);
730\f
731model_data *::model-function::model_create:cpu *processor
732 model_data *model_ptr = ZALLOC(model_data);
733 model_ptr->name = model_name[CURRENT_MODEL];
734 model_ptr->timing = model_time_mapping[CURRENT_MODEL];
735 model_ptr->processor = processor;
736 model_ptr->nr_cycles = 1;
737 model_ptr->busy_tail = &model_ptr->busy_head;
738 switch (CURRENT_MODEL) {
739 case MODEL_ppc601: model_ptr->max_nr_writebacks = 1; break; /* ??? */
740 case MODEL_ppc603: model_ptr->max_nr_writebacks = 2; break;
741 case MODEL_ppc603e: model_ptr->max_nr_writebacks = 2; break;
742 case MODEL_ppc604: model_ptr->max_nr_writebacks = 2; break;
743 default: error ("Unknown model %d\n", CURRENT_MODEL);
744 }
745 return model_ptr;
746
747void::model-function::model_init:model_data *model_ptr
748
749void::model-function::model_halt:model_data *model_ptr
750 /* Let pipeline drain */
751 while (model_ptr->busy_head.next)
752 model_new_cycle(model_ptr);
753
754unsigned_word::model-function::model_get_number_of_stalls:model_data *model_ptr
755 return (model_ptr->nr_stalls_data
756 + model_ptr->nr_stalls_unit
757 + model_ptr->nr_stalls_serialize
758 + model_ptr->nr_stalls_writeback);
759
760unsigned_word::model-function::model_get_number_of_cycles:model_data *model_ptr
761 return (model_ptr->nr_cycles);
762
763model_print *::model-function::model_mon_info:model_data *model_ptr
764 model_print *head;
765 model_print *tail;
766 ppc_function_unit i;
767 count_type nr_insns;
768 int j;
769
770 head = tail = ZALLOC(model_print);
771 tail->count = model_ptr->nr_cycles;
772 tail->name = "cycle";
773 tail->suffix_plural = "s";
774 tail->suffix_singular = "";
775
776 if (model_ptr->nr_stalls_data) {
777 tail->next = ZALLOC(model_print);
778 tail = tail->next;
779 tail->count = model_ptr->nr_stalls_data;
780 tail->name = "stall";
781 tail->suffix_plural = "s waiting for data";
782 tail->suffix_singular = " waiting for data";
783 }
784
785 if (model_ptr->nr_stalls_unit) {
786 tail->next = ZALLOC(model_print);
787 tail = tail->next;
788 tail->count = model_ptr->nr_stalls_unit;
789 tail->name = "stall";
790 tail->suffix_plural = "s waiting for a function unit";
791 tail->suffix_singular = " waiting for a function unit";
792 }
793
794 if (model_ptr->nr_stalls_serialize) {
795 tail->next = ZALLOC(model_print);
796 tail = tail->next;
797 tail->count = model_ptr->nr_stalls_serialize;
798 tail->name = "stall";
799 tail->suffix_plural = "s waiting for serialization";
800 tail->suffix_singular = " waiting for serialization";
801 }
802
803 if (model_ptr->nr_stalls_writeback) {
804 tail->next = ZALLOC(model_print);
805 tail = tail->next;
806 tail->count = model_ptr->nr_stalls_writeback;
807 tail->name = "";
808 tail->suffix_plural = "times a write-back slot was unavailable";
809 tail->suffix_singular = "time a writeback was unavailable";
810 }
811
812 if (model_ptr->nr_branches) {
813 tail->next = ZALLOC(model_print);
814 tail = tail->next;
815 tail->count = model_ptr->nr_branches;
816 tail->name = "branch";
817 tail->suffix_plural = "es";
818 tail->suffix_singular = "";
819 }
820
821 if (model_ptr->nr_branches_fallthrough) {
822 tail->next = ZALLOC(model_print);
823 tail = tail->next;
824 tail->count = model_ptr->nr_branches_fallthrough;
825 tail->name = "conditional branch";
826 tail->suffix_plural = "es fell through";
827 tail->suffix_singular = " fell through";
828 }
829
830 if (model_ptr->nr_branch_predict_trues) {
831 tail->next = ZALLOC(model_print);
832 tail = tail->next;
833 tail->count = model_ptr->nr_branch_predict_trues;
834 tail->name = "successful branch prediction";
835 tail->suffix_plural = "s";
836 tail->suffix_singular = "";
837 }
838
839 if (model_ptr->nr_branch_predict_falses) {
840 tail->next = ZALLOC(model_print);
841 tail = tail->next;
842 tail->count = model_ptr->nr_branch_predict_falses;
843 tail->name = "unsuccessful branch prediction";
844 tail->suffix_plural = "s";
845 tail->suffix_singular = "";
846 }
847
848 for (j = 0; j < (sizeof(ppc_branch_conditional_name) / sizeof(ppc_branch_conditional_name[0])) ; j++) {
849 if (model_ptr->nr_branch_conditional[j]) {
850 tail->next = ZALLOC(model_print);
851 tail = tail->next;
852 tail->count = model_ptr->nr_branch_conditional[j];
853 tail->name = ppc_branch_conditional_name[j];
854 tail->suffix_plural = " conditional branches";
855 tail->suffix_singular = " conditional branch";
856 }
857 }
858
859 for (j = 0; j < 9; j++) {
860 if (model_ptr->nr_mtcrf_crs[j]) {
861 tail->next = ZALLOC(model_print);
862 tail = tail->next;
863 tail->count = model_ptr->nr_mtcrf_crs[j];
864 tail->name = ppc_nr_mtcrf_crs[j];
865 tail->suffix_plural = " instructions";
866 tail->suffix_singular = " instruction";
867 }
868 }
869
870 nr_insns = 0;
871 for (i = PPC_UNIT_BAD; i < nr_ppc_function_units; i++) {
872 if (model_ptr->nr_units[i]) {
873 nr_insns += model_ptr->nr_units[i];
874 tail->next = ZALLOC(model_print);
875 tail = tail->next;
876 tail->count = model_ptr->nr_units[i];
877 tail->name = ppc_function_unit_name[i];
878 tail->suffix_plural = "s";
879 tail->suffix_singular = "";
880 }
881 }
882
883 tail->next = ZALLOC(model_print);
884 tail = tail->next;
885 tail->count = nr_insns;
886 tail->name = "instruction";
887 tail->suffix_plural = "s that were accounted for in timing info";
888 tail->suffix_singular = " that was accounted for in timing info";
889
890 tail->next = (model_print *)0;
891 return head;
892
893void::model-function::model_mon_info_free:model_data *model_ptr, model_print *ptr
894 while (ptr) {
895 model_print *next = ptr->next;
896 free((void *)ptr);
897 ptr = next;
898 }
899
900void::model-function::model_branches:model_data *model_ptr, int failed, int conditional
901 model_ptr->nr_units[PPC_UNIT_BPU]++;
902 if (failed)
903 model_ptr->nr_branches_fallthrough++;
904 else
905 model_ptr->nr_branches++;
906 if (conditional >= 0)
907 model_ptr->nr_branch_conditional[conditional]++;
908 model_new_cycle(model_ptr); /* A branch always ends the current cycle */
909
910void::model-function::model_branch_predict:model_data *model_ptr, int success
911 if (success)
912 model_ptr->nr_branch_predict_trues++;
913 else
914 model_ptr->nr_branch_predict_falses++;
915
916\f
917# The following (illegal) instruction is `known' by gen and is
918# called when ever an illegal instruction is encountered
919::internal::illegal
920 program_interrupt(processor, cia,
921 illegal_instruction_program_interrupt);
922
923
924# The following (floating point unavailable) instruction is `known' by gen
925# and is called when ever an a floating point instruction is to be
926# executed but floating point is make unavailable by the MSR
927::internal::floating_point_unavailable
928 floating_point_unavailable_interrupt(processor, cia);
929
930
931#
932# Floating point support functions
933#
934
935# Convert 32bit single to 64bit double
936unsigned64::function::DOUBLE:unsigned32 WORD
937 unsigned64 FRT;
938 if (EXTRACTED32(WORD, 1, 8) > 0
939 && EXTRACTED32(WORD, 1, 8) < 255) {
940 /* normalized operand */
941 int not_word_1_1 = !EXTRACTED32(WORD, 1, 1); /*2.6.3 bug*/
942 FRT = (INSERTED64(EXTRACTED32(WORD, 0, 1), 0, 1)
943 | INSERTED64(not_word_1_1, 2, 2)
944 | INSERTED64(not_word_1_1, 3, 3)
945 | INSERTED64(not_word_1_1, 4, 4)
946 | INSERTED64(EXTRACTED32(WORD, 2, 31), 5, (63 - 29)));
947 }
948 else if (EXTRACTED32(WORD, 1, 8) == 0
949 && EXTRACTED32(WORD, 9, 31) != 0) {
950 /* denormalized operand */
951 int sign = EXTRACTED32(WORD, 0, 0);
952 int exp = -126;
953 unsigned64 frac = INSERTED64(EXTRACTED32(WORD, 9, 31), 1, (52 - 29));
954 /* normalize the operand */
955 while (MASKED64(frac, 0, 0) == 0) {
956 frac <<= 1;
957 exp -= 1;
958 }
959 FRT = (INSERTED64(sign, 0, 0)
960 | INSERTED64(exp + 1023, 1, 11)
961 | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
962 }
963 else if (EXTRACTED32(WORD, 1, 8) == 255
964 || EXTRACTED32(WORD, 1, 31) == 0) {
965 FRT = (INSERTED64(EXTRACTED32(WORD, 0, 1), 0, 1)
966 | INSERTED64(EXTRACTED32(WORD, 1, 1), 2, 2)
967 | INSERTED64(EXTRACTED32(WORD, 1, 1), 3, 3)
968 | INSERTED64(EXTRACTED32(WORD, 1, 1), 4, 4)
969 | INSERTED64(EXTRACTED32(WORD, 2, 31), 5, (63 - 29)));
970 }
971 else {
972 error("DOUBLE - unknown case\n");
973 FRT = 0;
974 }
975 return FRT;
976
977# Convert 64bit single to 32bit double
978unsigned32::function::SINGLE:unsigned64 FRS
979 unsigned32 WORD;
980 if (EXTRACTED64(FRS, 1, 11) > 896
981 || EXTRACTED64(FRS, 1, 63) == 0) {
982 /* no denormalization required (includes Zero/Infinity/NaN) */
983 WORD = (INSERTED32(EXTRACTED64(FRS, 0, 1), 0, 1)
984 | INSERTED32(EXTRACTED64(FRS, 5, 34), 2, 31));
985 }
986 else if (874 <= EXTRACTED64(FRS, 1, 11)
987 && EXTRACTED64(FRS, 1, 11) <= 896) {
988 /* denormalization required */
989 int sign = EXTRACTED64(FRS, 0, 0);
990 int exp = EXTRACTED64(FRS, 1, 11) - 1023;
991 unsigned64 frac = (BIT64(0)
992 | INSERTED64(EXTRACTED64(FRS, 12, 63), 1, 52));
993 /* denormalize the operand */
994 while (exp < -126) {
995 frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63);
996 exp += 1;
997 }
998 WORD = (INSERTED32(sign, 0, 0)
999 | INSERTED32(0x00, 1, 8)
1000 | INSERTED32(EXTRACTED64(frac, 1, 23), 9, 31));
1001 }
1002 else {
1003 WORD = 0x0; /* ??? */
1004 }
1005 return WORD;
1006
1007
1008# round 64bit double to 64bit but single
1009void::function::Round_Single:cpu *processor, int sign, int *exp, unsigned64 *frac_grx
1010 /* comparisons ignore u bits */
1011 unsigned64 out;
1012 int inc = 0;
1013 int lsb = EXTRACTED64(*frac_grx, 23, 23);
1014 int gbit = EXTRACTED64(*frac_grx, 24, 24);
1015 int rbit = EXTRACTED64(*frac_grx, 25, 25);
1016 int xbit = EXTRACTED64(*frac_grx, 26, 55) != 0;
1017 if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
1018 if (lsb == 1 && gbit == 1) inc = 1;
1019 if (lsb == 0 && gbit == 1 && rbit == 1) inc = 1;
1020 if (lsb == 0 && gbit == 1 && xbit == 1) inc = 1;
1021 }
1022 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_pos_infinity) {
1023 if (sign == 0 && gbit == 1) inc = 1;
1024 if (sign == 0 && rbit == 1) inc = 1;
1025 if (sign == 0 && xbit == 1) inc = 1;
1026 }
1027 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_neg_infinity) {
1028 if (sign == 1 && gbit == 1) inc = 1;
1029 if (sign == 1 && rbit == 1) inc = 1;
1030 if (sign == 1 && xbit == 1) inc = 1;
1031 }
1032 /* work out addition in low 25 bits of out */
1033 out = EXTRACTED64(*frac_grx, 0, 23) + inc;
1034 *frac_grx = INSERTED64(out, 0, 23);
1035 if (out & BIT64(64 - 23 - 1 - 1)) {
1036 *frac_grx = (BIT64(0) |
1037 INSERTED64(EXTRACTED64(*frac_grx, 0, 22), 1, 23));
1038 *exp = *exp + 1;
1039 }
1040 /* frac_grx[24:52] = 0 already */
1041 FPSCR_SET_FR(inc);
1042 FPSCR_SET_FI(gbit || rbit || xbit);
1043
1044
1045#
1046void::function::Round_Integer:cpu *processor, int sign, unsigned64 *frac, int *frac64, int gbit, int rbit, int xbit, fpscreg round_mode
1047 int inc = 0;
1048 if (round_mode == fpscr_rn_round_to_nearest) {
1049 if (*frac64 == 1 && gbit == 1) inc = 1;
1050 if (*frac64 == 0 && gbit == 1 && rbit == 1) inc = 1;
1051 if (*frac64 == 0 && gbit == 1 && xbit == 1) inc = 1;
1052 }
1053 if (round_mode == fpscr_rn_round_towards_pos_infinity) {
1054 if (sign == 0 && gbit == 1) inc = 1;
1055 if (sign == 0 && rbit == 1) inc = 1;
1056 if (sign == 0 && xbit == 1) inc = 1;
1057 }
1058 if (round_mode == fpscr_rn_round_towards_neg_infinity) {
1059 if (sign == 1 && gbit == 1) inc = 1;
1060 if (sign == 1 && rbit == 1) inc = 1;
1061 if (sign == 1 && xbit == 1) inc = 1;
1062 }
1063 /* frac[0:64] = frac[0:64} + inc */
1064 *frac += (*frac64 && inc ? 1 : 0);
1065 *frac64 = (*frac64 + inc) & 0x1;
1066 FPSCR_SET_FR(inc);
1067 FPSCR_SET_FI(gbit | rbit | xbit);
1068
1069
1070void::function::Round_Float:cpu *processor, int sign, int *exp, unsigned64 *frac, fpscreg round_mode
1071 int carry_out;
1072 int inc = 0;
1073 int lsb = EXTRACTED64(*frac, 52, 52);
1074 int gbit = EXTRACTED64(*frac, 53, 53);
1075 int rbit = EXTRACTED64(*frac, 54, 54);
1076 int xbit = EXTRACTED64(*frac, 55, 55);
1077 if (round_mode == fpscr_rn_round_to_nearest) {
1078 if (lsb == 1 && gbit == 1) inc = 1;
1079 if (lsb == 0 && gbit == 1 && rbit == 1) inc = 1;
1080 if (lsb == 0 && gbit == 1 && xbit == 1) inc = 1;
1081 }
1082 if (round_mode == fpscr_rn_round_towards_pos_infinity) {
1083 if (sign == 0 && gbit == 1) inc = 1;
1084 if (sign == 0 && rbit == 1) inc = 1;
1085 if (sign == 0 && xbit == 1) inc = 1;
1086 }
1087 if (round_mode == fpscr_rn_round_towards_neg_infinity) {
1088 if (sign == 1 && gbit == 1) inc = 1;
1089 if (sign == 1 && rbit == 1) inc = 1;
1090 if (sign == 1 && xbit == 1) inc = 1;
1091 }
1092 /* frac//carry_out = frac + inc */
1093 *frac = (*frac >> 1) + (INSERTED64(inc, 52, 52) >> 1);
1094 carry_out = EXTRACTED64(*frac, 0, 0);
1095 *frac <<= 1;
1096 if (carry_out == 1) *exp = *exp + 1;
1097 FPSCR_SET_FR(inc);
1098 FPSCR_SET_FI(gbit | rbit | xbit);
1099 FPSCR_SET_XX(FPSCR & fpscr_fi);
1100
1101
1102# conversion of FP to integer
1103void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64 *frt, unsigned64 frb, fpscreg round_mode, int tgt_precision
1104 int i;
1105 int exp = 0;
1106 unsigned64 frac = 0;
1107 int frac64 = 0;
1108 int gbit = 0;
1109 int rbit = 0;
1110 int xbit = 0;
1111 int sign = EXTRACTED64(frb, 0, 0);
1112 /***/
1113 if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 63) == 0)
1114 GOTO(Infinity_Operand);
1115 if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 0)
1116 GOTO(SNaN_Operand);
1117 if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 1)
1118 GOTO(QNaN_Operand);
1119 if (EXTRACTED64(frb, 1, 11) > 1086) GOTO(Large_Operand);
1120 if (EXTRACTED64(frb, 1, 11) > 0) exp = EXTRACTED64(frb, 1, 11) - 1023;
1121 if (EXTRACTED64(frb, 1, 11) == 0) exp = -1022;
1122 if (EXTRACTED64(frb, 1, 11) > 0) { /* normal */
1123 frac = BIT64(1) | INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
1124 frac64 = 0;
1125 }
1126 if (EXTRACTED64(frb, 1, 11) == 0) { /* denorm */
1127 frac = INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
1128 frac64 = 0;
1129 }
1130 gbit = 0, rbit = 0, xbit = 0;
1131 for (i = 1; i <= 63 - exp; i++) {
1132 xbit = rbit | xbit;
1133 rbit = gbit;
1134 gbit = frac64;
1135 frac64 = EXTRACTED64(frac, 63, 63);
1136 frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63);
1137 }
1138 Round_Integer(processor, sign, &frac, &frac64, gbit, rbit, xbit, round_mode);
1139 if (sign == 1) { /* frac[0:64] = ~frac[0:64] + 1 */
1140 frac = ~frac;
1141 frac64 ^= 1;
1142 frac += (frac64 ? 1 : 0);
1143 frac64 = (frac64 + 1) & 0x1;
1144 }
1145 if (tgt_precision == 32 /* can ignore frac64 in compare */
1146 && (signed64)frac > (signed64)MASK64(33+1, 63)/*2^31-1 >>1*/)
1147 GOTO(Large_Operand);
1148 if (tgt_precision == 64 /* can ignore frac64 in compare */
1149 && (signed64)frac > (signed64)MASK64(1+1, 63)/*2^63-1 >>1*/)
1150 GOTO(Large_Operand);
1151 if (tgt_precision == 32 /* can ignore frac64 in compare */
1152 && (signed64)frac < (signed64)MASK64(0, 32+1)/*-2^31 >>1*/)
1153 GOTO(Large_Operand);
1154 if (tgt_precision == 64 /* can ignore frac64 in compare */
1155 && (signed64)frac < (signed64)MASK64(0, 0+1)/*-2^63 >>1*/)
1156 GOTO(Large_Operand);
1157 FPSCR_SET_XX(FPSCR & fpscr_fi);
1158 if (tgt_precision == 32)
1159 *frt = MASKED64(*frt, 0, 31) | (EXTRACTED64(frac, 33, 63) << 1) | frac64;
1160 if (tgt_precision == 64)
1161 *frt = (EXTRACTED64(frac, 1, 63) << 1) | frac64;
1162 /*FPSCR[fprf] = undefined */
1163 GOTO(Done);
1164 /**/
1165 LABEL(Infinity_Operand):
1166 FPSCR_SET_FR(0);
1167 FPSCR_SET_FI(0);
1168 FPSCR_OR_VX(fpscr_vxcvi);
1169 if ((FPSCR & fpscr_ve) == 0) {
1170 if (tgt_precision == 32) {
1171 if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7FFFFFFF;
1172 if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1173 }
1174 else {
1175 if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/
1176 if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
1177 }
1178 /* FPSCR[FPRF] = undefined */
1179 }
1180 GOTO(Done);
1181 /**/
1182 LABEL(SNaN_Operand):
1183 FPSCR_SET_FR(0);
1184 FPSCR_SET_FI(0);
1185 FPSCR_OR_VX(fpscr_vxsnan | fpscr_vxcvi);
1186 if ((FPSCR & fpscr_ve) == 0) {
1187 if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1188 if (tgt_precision == 64) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
1189 /* FPSCR[fprf] = undefined */
1190 }
1191 GOTO(Done);
1192 /**/
1193 LABEL(QNaN_Operand):
1194 FPSCR_SET_FR(0);
1195 FPSCR_SET_FI(0);
1196 FPSCR_OR_VX(fpscr_vxcvi);
1197 if ((FPSCR & fpscr_ve) == 0) {
1198 if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1199 if (tgt_precision == 64) *frt = BIT64(0);/*0x8000_0000_0000_0000*/
1200 /* FPSCR[fprf] = undefined */
1201 }
1202 GOTO(Done);
1203 /**/
1204 LABEL(Large_Operand):
1205 FPSCR_SET_FR(0);
1206 FPSCR_SET_FI(0);
1207 FPSCR_OR_VX(fpscr_vxcvi);
1208 if ((FPSCR & fpscr_ve) == 0) {
1209 if (tgt_precision == 32) {
1210 if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7fffffff;
1211 if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
1212 }
1213 else {
1214 if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/
1215 if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
1216 }
1217 /* FPSCR[fprf] = undefined */
1218 }
1219 /**/
1220 LABEL(Done):
1221
1222
1223# extract out raw fields of a FP number
1224int::function::sign:unsigned64 FRS
1225 return (MASKED64(FRS, 0, 0)
1226 ? -1
1227 : 1);
1228int::function::biased_exp:unsigned64 frs, int single
1229 if (single)
1230 return EXTRACTED64(frs, 1, 8);
1231 else
1232 return EXTRACTED64(frs, 1, 11);
1233unsigned64::function::fraction:unsigned64 frs, int single
1234 if (single)
1235 return EXTRACTED64(frs, 9, 31);
1236 else
1237 return EXTRACTED64(frs, 12, 63);
1238
1239# a number?, each of the below return +1 or -1 (based on sign bit)
1240# if true.
1241int::function::is_nor:unsigned64 frs, int single
1242 int exp = biased_exp(frs, single);
1243 return (exp >= 1
1244 && exp <= (single ? 254 : 2046));
1245int::function::is_zero:unsigned64 FRS
1246 return (MASKED64(FRS, 1, 63) == 0
1247 ? sign(FRS)
1248 : 0);
1249int::function::is_den:unsigned64 frs, int single
1250 int exp = biased_exp(frs, single);
1251 unsigned64 frac = fraction(frs, single);
1252 return (exp == 0 && frac != 0
1253 ? sign(frs)
1254 : 0);
1255int::function::is_inf:unsigned64 frs, int single
1256 int exp = biased_exp(frs, single);
1257 unsigned64 frac = fraction(frs, single);
1258 return (exp == (single ? 255 : 2047) && frac == 0
1259 ? sign(frs)
1260 : 0);
1261int::function::is_NaN:unsigned64 frs, int single
1262 int exp = biased_exp(frs, single);
1263 unsigned64 frac = fraction(frs, single);
1264 return (exp == (single ? 255 : 2047) && frac != 0
1265 ? sign(frs)
1266 : 0);
1267int::function::is_SNaN:unsigned64 frs, int single
1268 return (is_NaN(frs, single)
1269 && !(frs & (single ? MASK64(9, 9) : MASK64(12, 12)))
1270 ? sign(frs)
1271 : 0);
1272int::function::is_QNaN:unsigned64 frs, int single
1273 return (is_NaN(frs, single) && !is_SNaN(frs, single));
1274int::function::is_less_than:unsigned64 *fra, unsigned64 *frb
1275 return *(double*)fra < *(double*)frb;
1276int::function::is_greater_than:unsigned64 *fra, unsigned64 *frb
1277 return *(double*)fra > *(double*)frb;
1278int::function::is_equan_to:unsigned64 *fra, unsigned64 *frb
1279 return *(double*)fra == *(double*)frb;
1280
1281
1282# which quiet nan should become the result
1283unsigned64::function::select_qnan:unsigned64 fra, unsigned64 frb, unsigned64 frc, int instruction_is_frsp, int generate_qnan, int single
1284 unsigned64 frt = 0;
1285 if (is_NaN(fra, single))
1286 frt = fra;
1287 else if (is_NaN(frb, single))
1288 if (instruction_is_frsp)
1289 frt = MASKED64(frb, 0, 34);
1290 else
1291 frt = frb;
1292 else if (is_NaN(frc, single))
1293 frt = frc;
1294 else if (generate_qnan)
1295 frt = MASK64(1, 12); /* 0x7FF8_0000_0000_0000 */
1296 else
1297 error("select_qnan - default reached\n");
1298 return frt;
1299
1300
1301# detect invalid operation
1302int::function::is_invalid_operation:cpu *processor, unsigned_word cia, unsigned64 fra, unsigned64 frb, fpscreg check, int single, int negate
1303 int fail = 0;
1304 if ((check & fpscr_vxsnan)
1305 && (is_SNaN(fra, single) || is_SNaN(frb, single))) {
1306 FPSCR_OR_VX(fpscr_vxsnan);
1307 fail = 1;
1308 }
1309 if ((check & fpscr_vxisi)
1310 && (is_inf(fra, single) && is_inf(frb, single))
1311 && ((negate && sign(fra) != sign(frb))
1312 || (!negate && sign(fra) == sign(frb)))) {
1313 /*FIXME: don't handle inf-inf VS inf+-inf */
1314 FPSCR_OR_VX(fpscr_vxisi);
1315 fail = 1;
1316 }
1317 if ((check & fpscr_vxidi)
1318 && (is_inf(fra, single) && is_inf(frb, single))) {
1319 FPSCR_OR_VX(fpscr_vxidi);
1320 fail = 1;
1321 }
1322 if ((check & fpscr_vxzdz)
1323 && (is_zero(fra) && is_zero(frb))) {
1324 FPSCR_OR_VX(fpscr_vxzdz);
1325 fail = 1;
1326 }
1327 if ((check & fpscr_vximz)
1328 && (is_zero(fra) && is_inf(frb, single))) {
1329 FPSCR_OR_VX(fpscr_vximz);
1330 fail = 1;
1331 }
1332 if ((check & fpscr_vxvc)
1333 && (is_NaN(fra, single) || is_NaN(frb, single))) {
1334 FPSCR_OR_VX(fpscr_vxvc);
1335 fail = 1;
1336 }
1337 if ((check & fpscr_vxsoft)) {
1338 FPSCR_OR_VX(fpscr_vxsoft);
1339 fail = 1;
1340 }
1341 if ((check & fpscr_vxsqrt)
1342 && sign(fra) < 0) {
1343 FPSCR_OR_VX(fpscr_vxsqrt);
1344 fail = 1;
1345 }
1346 /* if ((check && fpscr_vxcvi) {
1347 && (is_inf(fra, single) || is_NaN(fra, single) || is_large(fra, single)))
1348 FPSCR_OR_VX(fpscr_vxcvi);
1349 fail = 1;
1350 }
1351 */
1352 return fail;
1353
1354
1355
1356
1357
1358# handle case of invalid operation
1359void::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
1360 if (FPSCR & fpscr_ve) {
1361 /* invalid operation exception enabled */
1362 /* FRT unchaged */
1363 FPSCR_SET_FR(0);
1364 FPSCR_SET_FI(0);
1365 /* fpscr_FPRF unchanged */
1366 }
1367 else {
1368 /* invalid operation exception disabled */
1369 if (instruction_is_convert_to_64bit) {
1370 error("oopsi");
1371 }
1372 else if (instruction_is_convert_to_32bit) {
1373 error("oopsi");
1374 }
1375 else { /* arrith, frsp */
1376 *frt = select_qnan(fra, frb, frc,
1377 instruction_is_frsp, 1/*generate*/, single);
1378 FPSCR_SET_FR(0);
1379 FPSCR_SET_FI(0);
1380 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
1381 }
1382 }
1383
1384
1385
1386
1387# detect divide by zero
1388int::function::is_invalid_zero_divide:cpu *processor, unsigned_word cia, unsigned64 fra, unsigned64 frb, int single
1389 int fail = 0;
1390 if (is_zero (frb)) {
1391 FPSCR_SET_ZX (1);
1392 fail = 1;
1393 }
1394 return fail;
1395
1396
1397
1398
1399# handle case of invalid operation
1400void::function::invalid_zero_divide_operation:cpu *processor, unsigned_word cia, unsigned64 *frt, unsigned64 fra, unsigned64 frb, int single
1401 if (FPSCR & fpscr_ze) {
1402 /* zero-divide exception enabled */
1403 /* FRT unchaged */
1404 FPSCR_SET_FR(0);
1405 FPSCR_SET_FI(0);
1406 /* fpscr_FPRF unchanged */
1407 }
1408 else {
1409 /* zero-divide exception disabled */
1410 FPSCR_SET_FR(0);
1411 FPSCR_SET_FI(0);
1412 if ((sign (fra) < 0 && sign (frb) < 0)
1413 || (sign (fra) > 0 && sign (frb) > 0)) {
1414 *frt = MASK64 (1, 11); /* 0 : 2047 : 0..0 */
1415 FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
1416 }
1417 else {
1418 *frt = MASK64 (0, 11); /* 1 : 2047 : 0..0 */
1419 FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
1420 }
1421 }
1422
1423
1424
1425
1426
1427#
1428# 0.0.0.0 Illegal instruction used for kernel mode emulation
1429#
14300.0,6./,11./,16./,21./,31.1:X:::instruction_call
1431 if (!os_emul_instruction_call(processor, cia, real_addr(cia, 1)))
1432 program_interrupt(processor, cia,
1433 illegal_instruction_program_interrupt);
1434
1435#
1436# I.2.4.1 Branch Instructions
1437#
14380.18,6.LI,30.AA,31.LK:I:::Branch
1439*601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1440*603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1441*603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1442*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
7a292a7a 1443 /* option_mpc860c0:
c906108c
SS
1444 No problem here because this branch is predicted taken (unconditional). */
1445 if (AA) NIA = IEA(EXTS(LI_0b00));
1446 else NIA = IEA(CIA + EXTS(LI_0b00));
1447 if (LK) LR = (spreg)CIA+4;
1448 if (CURRENT_MODEL_ISSUE > 0)
1449 model_branches(cpu_model(processor), 1, -1);
1450
14510.16,6.BO,11.BI,16.BD,30.AA,31.LK:B:::Branch Conditional
1452*601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1453*603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1454*603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1455*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1456 int M, ctr_ok, cond_ok, succeed;
1457 if (CURRENT_MODEL_ISSUE > 0 && ! BO{0})
1458 model_wait_for_cr(cpu_model(processor), BIT32_BI);
1459 if (is_64bit_implementation && is_64bit_mode) M = 0;
1460 else M = 32;
1461 if (!BO{2}) CTR = CTR - 1;
1462 ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != (BO{3}));
1463 cond_ok = BO{0} || ((CR{BI}) == (BO{1}));
1464 if (ctr_ok && cond_ok) {
1465 if (AA) NIA = IEA(EXTS(BD_0b00));
1466 else NIA = IEA(CIA + EXTS(BD_0b00));
1467 succeed = 1;
1468 }
1469 else
1470 succeed = 0;
1471 if (LK) LR = (spreg)IEA(CIA + 4);
7a292a7a
SS
1472 if (option_mpc860c0 && (!BO{0} || !BO{2}) && !BO{4}) {
1473 /* This branch is predicted as "normal".
c906108c
SS
1474 If this is a forward branch and it is near the end of a page,
1475 we've detected a problematic branch. */
1476 if (succeed && NIA > CIA) {
1477 if (PAGE_SIZE - (CIA & (PAGE_SIZE-1)) <= option_mpc860c0)
1478 program_interrupt(processor, cia, mpc860c0_instruction_program_interrupt);
1479 }
1480 }
c906108c
SS
1481 if (CURRENT_MODEL_ISSUE > 0)
1482 model_branches(cpu_model(processor), succeed, BO);
1483 if (! BO{0}) {
1484 int reverse;
1485 if (BO{4}) { /* branch prediction bit set, reverse sense of test */
1486 reverse = EXTS(BD_0b00) < 0;
1487 } else { /* branch prediction bit not set */
1488 reverse = EXTS(BD_0b00) >= 0;
1489 }
1490 if (CURRENT_MODEL_ISSUE > 0)
1491 model_branch_predict(cpu_model(processor), reverse ? !succeed : succeed);
1492 }
1493
14940.19,6.BO,11.BI,16./,21.16,31.LK:XL:::Branch Conditional to Link Register
1495*601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1496*603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1497*603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1498*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1499 int M, ctr_ok, cond_ok, succeed;
1500 if (is_64bit_implementation && is_64bit_mode) M = 0;
1501 else M = 32;
1502 if (CURRENT_MODEL_ISSUE > 0 && ! BO{0})
1503 model_wait_for_cr(cpu_model(processor), BIT32_BI);
1504 if (!BO{2}) CTR = CTR - 1;
1505 ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != BO{3});
1506 cond_ok = BO{0} || (CR{BI} == BO{1});
1507 if (ctr_ok && cond_ok) {
1508 NIA = IEA(LR_0b00);
1509 succeed = 1;
1510 }
1511 else
1512 succeed = 0;
1513 if (LK) LR = (spreg)IEA(CIA + 4);
7a292a7a 1514 if (option_mpc860c0 && (!BO{0} || !BO{2}) && !BO{4}) {
c906108c
SS
1515 /* This branch is predicted as not-taken.
1516 If this is a forward branch and it is near the end of a page,
1517 we've detected a problematic branch. */
1518 if (succeed && NIA > CIA) {
1519 if (PAGE_SIZE - (CIA & (PAGE_SIZE-1)) <= option_mpc860c0)
1520 program_interrupt(processor, cia, mpc860c0_instruction_program_interrupt);
1521 }
1522 }
c906108c
SS
1523 if (CURRENT_MODEL_ISSUE > 0) {
1524 model_branches(cpu_model(processor), succeed, BO);
1525 if (! BO{0})
1526 model_branch_predict(cpu_model(processor), BO{4} ? !succeed : succeed);
1527 }
1528
15290.19,6.BO,11.BI,16./,21.528,31.LK:XL:::Branch Conditional to Count Register
1530*601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1531*603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1532*603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1533*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1534 int cond_ok, succeed;
1535 if (CURRENT_MODEL_ISSUE > 0 && ! BO{0})
1536 model_wait_for_cr(cpu_model(processor), BIT32_BI);
1537 cond_ok = BO{0} || (CR{BI} == BO{1});
1538 if (cond_ok) {
1539 NIA = IEA(CTR_0b00);
1540 succeed = 1;
1541 }
1542 else
1543 succeed = 0;
1544 if (LK) LR = (spreg)IEA(CIA + 4);
7a292a7a 1545 if (option_mpc860c0 && (!BO{0} || !BO{2}) && !BO{4}) {
c906108c
SS
1546 /* This branch is predicted as not-taken.
1547 If this is a forward branch and it is near the end of a page,
1548 we've detected a problematic branch. */
1549 if (succeed && NIA > CIA) {
1550 if (PAGE_SIZE - (CIA & (PAGE_SIZE-1)) <= option_mpc860c0)
1551 program_interrupt(processor, cia, mpc860c0_instruction_program_interrupt);
1552 }
1553 }
c906108c
SS
1554 if (CURRENT_MODEL_ISSUE > 0) {
1555 model_branches(cpu_model(processor), succeed, BO);
1556 if (! BO{0})
1557 model_branch_predict(cpu_model(processor), BO{4} ? !succeed : succeed);
1558 }
1559
1560#
1561# I.2.4.2 System Call Instruction
1562#
15630.17,6./,11./,16./,30.1,31./:SC:::System Call
1564*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1565*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
1566*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
1567*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1568 if (CURRENT_MODEL_ISSUE > 0)
1569 model_serialize(MY_INDEX, cpu_model(processor));
1570 system_call_interrupt(processor, cia);
1571
1572#
1573# I.2.4.3 Condition Register Logical Instructions
1574#
15750.19,6.BT,11.BA,16.BB,21.257,31./:XL::crand:Condition Register AND
1576*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1577*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1578*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1579*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1580 BLIT32(CR, BT, CR{BA} && CR{BB});
1581 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1582
15830.19,6.BT,11.BA,16.BB,21.449,31./:XL::cror:Condition Register OR
1584*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1585*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1586*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1587*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1588 BLIT32(CR, BT, CR{BA} || CR{BB});
1589 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1590
15910.19,6.BT,11.BA,16.BB,21.193,31./:XL::crxor:Condition Register XOR
1592*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1593*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1594*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1595*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1596 BLIT32(CR, BT, CR{BA} != CR{BB});
1597 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1598
15990.19,6.BT,11.BA,16.BB,21.225,31./:XL::crnand:Condition Register NAND
1600*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1601*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1602*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1603*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1604 BLIT32(CR, BT, !(CR{BA} && CR{BB}));
1605 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1606
16070.19,6.BT,11.BA,16.BB,21.33,31./:XL::crnor:Condition Register NOR
1608*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1609*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1610*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1611*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1612 BLIT32(CR, BT, !(CR{BA} || CR{BB}));
1613 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1614
16150.19,6.BT,11.BA,16.BB,21.289,31./:XL::creqv:Condition Register Equivalent
1616*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1617*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1618*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1619*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1620 BLIT32(CR, BT, CR{BA} == CR{BB});
1621 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1622
16230.19,6.BT,11.BA,16.BB,21.129,31./:XL::crandc:Condition Register AND with Complement
1624*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1625*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1626*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1627*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1628 BLIT32(CR, BT, CR{BA} && !CR{BB});
1629 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1630
16310.19,6.BT,11.BA,16.BB,21.417,31./:XL::crorc:Condition Register OR with Complement
1632*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1633*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1634*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1635*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1636 BLIT32(CR, BT, CR{BA} || !CR{BB});
1637 PPC_INSN_CR(BT_BITMASK, BA_BITMASK | BB_BITMASK);
1638
1639#
1640# I.2.4.4 Condition Register Field Instruction
1641#
16420.19,6.BF,9./,11.BFA,14./,16./,21.0,31./:XL:::Move Condition Register Field
1643*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1644*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1645*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
1646*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1647 MBLIT32(CR, 4*BF, 4*BF+3, EXTRACTED32(CR, 4*BFA, 4*BFA+3));
1648 PPC_INSN_CR(BF_BITMASK, 1 << BFA);
1649
1650
1651#
1652# I.3.3.2 Fixed-Point Load Instructions
1653#
1654
16550.34,6.RT,11.RA,16.D:D:::Load Byte and Zero
1656*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1657*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1658*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1659*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1660 unsigned_word b;
1661 unsigned_word EA;
1662 if (RA_is_0) b = 0;
1663 else b = *rA;
1664 EA = b + EXTS(D);
1665 *rT = MEM(unsigned, EA, 1);
1666 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
1667
1668
16690.31,6.RT,11.RA,16.RB,21.87,31./:X:::Load Byte and Zero Indexed
1670*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1671*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1672*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1673*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1674 unsigned_word b;
1675 unsigned_word EA;
1676 if (RA_is_0) b = 0;
1677 else b = *rA;
1678 EA = b + *rB;
1679 *rT = MEM(unsigned, EA, 1);
1680 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
1681
16820.35,6.RT,11.RA,16.D:D:::Load Byte and Zero with Update
1683*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1684*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1685*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1686*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1687 unsigned_word EA;
1688 if (RA_is_0 || RA == RT)
1689 program_interrupt(processor, cia,
1690 illegal_instruction_program_interrupt);
1691 EA = *rA + EXTS(D);
1692 *rT = MEM(unsigned, EA, 1);
1693 *rA = EA;
1694 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK, 0);
1695
16960.31,6.RT,11.RA,16.RB,21.119,31./:X:::Load Byte and Zero with Update Indexed
1697*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1698*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1699*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1700*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1701 unsigned_word EA;
1702 if (RA_is_0 || RA == RT)
1703 program_interrupt(processor, cia,
1704 illegal_instruction_program_interrupt);
1705 EA = *rA + *rB;
1706 *rT = MEM(unsigned, EA, 1);
1707 *rA = EA;
1708 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK | RB_BITMASK, 0);
1709
17100.40,6.RT,11.RA,16.D:D:::Load Halfword and Zero
1711*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1712*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1713*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1714*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1715 unsigned_word b;
1716 unsigned_word EA;
1717 if (RA_is_0) b = 0;
1718 else b = *rA;
1719 EA = b + EXTS(D);
1720 *rT = MEM(unsigned, EA, 2);
1721 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
1722
17230.31,6.RT,11.RA,16.RB,21.279,31./:X:::Load Halfword and Zero Indexed
1724*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1725*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1726*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1727*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1728 unsigned_word b;
1729 unsigned_word EA;
1730 if (RA_is_0) b = 0;
1731 else b = *rA;
1732 EA = b + *rB;
1733 *rT = MEM(unsigned, EA, 2);
1734 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
1735
17360.41,6.RT,11.RA,16.D:D:::Load Halfword and Zero with Update
1737*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1738*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1739*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1740*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1741 unsigned_word EA;
1742 if (RA_is_0 || RA == RT)
1743 program_interrupt(processor, cia,
1744 illegal_instruction_program_interrupt);
1745 EA = *rA + EXTS(D);
1746 *rT = MEM(unsigned, EA, 2);
1747 *rA = EA;
1748 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK, 0);
1749
17500.31,6.RT,11.RA,16.RB,21.311,31./:X:::Load Halfword and Zero with Update Indexed
1751*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1752*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1753*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1754*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1755 unsigned_word EA;
1756 if (RA_is_0 || RA == RT)
1757 program_interrupt(processor, cia,
1758 illegal_instruction_program_interrupt);
1759 EA = *rA + *rB;
1760 *rT = MEM(unsigned, EA, 2);
1761 *rA = EA;
1762 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK | RB_BITMASK, 0);
1763
17640.42,6.RT,11.RA,16.D:D:::Load Halfword Algebraic
1765*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 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, 2, 0
1769 unsigned_word b;
1770 unsigned_word EA;
1771 if (RA_is_0) b = 0;
1772 else b = *rA;
1773 EA = b + EXTS(D);
1774 *rT = MEM(signed, EA, 2);
1775 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
1776
17770.31,6.RT,11.RA,16.RB,21.343,31./:X:::Load Halfword Algebraic Indexed
1778*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1779*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1780*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1781*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1782 unsigned_word b;
1783 unsigned_word EA;
1784 if (RA_is_0) b = 0;
1785 else b = *rA;
1786 EA = b + *rB;
1787 *rT = MEM(signed, EA, 2);
1788 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
1789
17900.43,6.RT,11.RA,16.D:D:::Load Halfword Algebraic with Update
1791*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1792*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1793*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1794*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1795 unsigned_word EA;
1796 if (RA_is_0 || RA == RT)
1797 program_interrupt(processor, cia,
1798 illegal_instruction_program_interrupt);
1799 EA = *rA + EXTS(D);
1800 *rT = MEM(signed, EA, 2);
1801 *rA = EA;
1802 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK, 0);
1803
18040.31,6.RT,11.RA,16.RB,21.375,31./:X:::Load Halfword Algebraic with Update Indexed
1805*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1806*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1807*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1808*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1809 unsigned_word EA;
1810 if (RA_is_0 || RA == RT)
1811 program_interrupt(processor, cia,
1812 illegal_instruction_program_interrupt);
1813 EA = *rA + *rB;
1814 *rT = MEM(signed, EA, 2);
1815 *rA = EA;
1816 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK | RB_BITMASK, 0);
1817
18180.32,6.RT,11.RA,16.D:D:::Load Word and Zero
1819*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1820*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1821*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1822*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1823 unsigned_word b;
1824 unsigned_word EA;
1825 if (RA_is_0) b = 0;
1826 else b = *rA;
1827 EA = b + EXTS(D);
1828 *rT = MEM(unsigned, EA, 4);
1829 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
1830
18310.31,6.RT,11.RA,16.RB,21.23,31./:X:::Load Word and Zero Indexed
1832*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1833*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1834*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1835*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1836 unsigned_word b;
1837 unsigned_word EA;
1838 if (RA_is_0) b = 0;
1839 else b = *rA;
1840 EA = b + *rB;
1841 *rT = MEM(unsigned, EA, 4);
1842 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
1843
18440.33,6.RT,11.RA,16.D:D:::Load Word and Zero with Update
1845*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1846*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1847*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1848*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1849 unsigned_word EA;
1850 if (RA_is_0 || RA == RT)
1851 program_interrupt(processor, cia,
1852 illegal_instruction_program_interrupt);
1853 EA = *rA + EXTS(D);
1854 *rT = MEM(unsigned, EA, 4);
1855 *rA = EA;
1856 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK, 0);
1857
18580.31,6.RT,11.RA,16.RB,21.55,31./:X:::Load Word and Zero with Update Indexed
1859*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
1860*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1861*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1862*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1863 unsigned_word EA;
1864 if (RA_is_0 || RA == RT)
1865 program_interrupt(processor, cia,
1866 illegal_instruction_program_interrupt);
1867 EA = *rA + *rB;
1868 *rT = MEM(unsigned, EA, 4);
1869 *rA = EA;
1870 PPC_INSN_INT(RT_BITMASK | RA_BITMASK, RA_BITMASK | RB_BITMASK, 0);
1871
18720.58,6.RT,11.RA,16.DS,30.2:DS:64::Load Word Algebraic
1873# unsigned_word b;
1874# unsigned_word EA;
1875# if (RA_is_0) b = 0;
1876# else b = *rA;
1877# EA = b + EXTS(DS_0b00);
1878# *rT = MEM(signed, EA, 4);
1879
18800.31,6.RT,11.RA,16.RB,21.341,31./:X:64::Load Word Algebraic Indexed
1881# unsigned_word b;
1882# unsigned_word EA;
1883# if (RA_is_0) b = 0;
1884# else b = *rA;
1885# EA = b + *rB;;
1886# *rT = MEM(signed, EA, 4);
1887
18880.31,6.RT,11.RA,16.RB,21.373,31./:X:64::Load Word Algebraic with Update Indexed
1889# unsigned_word EA;
1890# if (RA_is_0 || RA == RT)
1891# program_interrupt(processor, cia
1892# illegal_instruction_program_interrupt);
1893# EA = *rA + *rB;
1894# *rT = MEM(signed, EA, 4);
1895# *rA = EA;
1896
18970.58,6.RT,11.RA,16.DS,30.0:DS:64::Load Doubleword
1898# unsigned_word b;
1899# unsigned_word EA;
1900# if (RA_is_0) b = 0;
1901# else b = *rA;
1902# EA = b + EXTS(DS_0b00);
1903# *rT = MEM(unsigned, EA, 8);
1904
19050.31,6.RT,11.RA,16.RB,21.21,31./:X:64::Load Doubleword Indexed
1906# unsigned_word b;
1907# unsigned_word EA;
1908# if (RA_is_0) b = 0;
1909# else b = *rA;
1910# EA = b + *rB;
1911# *rT = MEM(unsigned, EA, 8);
1912
19130.58,6.RT,11.RA,16.DS,30.1:DS:64::Load Doubleword with Update
1914# unsigned_word EA;
1915# if (RA_is_0 || RA == RT)
1916# program_interrupt(processor, cia
1917# illegal_instruction_program_interrupt);
1918# EA = *rA + EXTS(DS_0b00);
1919# *rT = MEM(unsigned, EA, 8);
1920# *rA = EA;
1921
19220.31,6.RT,11.RA,16.RB,21.53,31./:DS:64::Load Doubleword with Update Indexed
1923# unsigned_word EA;
1924# if (RA_is_0 || RA == RT)
1925# program_interrupt(processor, cia
1926# illegal_instruction_program_interrupt);
1927# EA = *rA + *rB;
1928# *rT = MEM(unsigned, EA, 8);
1929# *rA = EA;
1930
1931
1932
1933#
1934# I.3.3.3 Fixed-Point Store Instructions
1935#
1936
19370.38,6.RS,11.RA,16.D:D:::Store Byte
1938*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1939*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1940*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1941*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1942 unsigned_word b;
1943 unsigned_word EA;
1944 if (RA_is_0) b = 0;
1945 else b = *rA;
1946 EA = b + EXTS(D);
1947 STORE(EA, 1, *rS);
1948 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RS_BITMASK, 0);
1949
19500.31,6.RS,11.RA,16.RB,21.215,31./:X:::Store Byte Indexed
1951*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1952*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1953*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1954*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1955 unsigned_word b;
1956 unsigned_word EA;
1957 if (RA_is_0) b = 0;
1958 else b = *rA;
1959 EA = b + *rB;
1960 STORE(EA, 1, *rS);
1961 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
1962
19630.39,6.RS,11.RA,16.D:D:::Store Byte with Update
1964*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1965*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1966*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1967*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1968 unsigned_word EA;
1969 if (RA_is_0)
1970 program_interrupt(processor, cia,
1971 illegal_instruction_program_interrupt);
1972 EA = *rA + EXTS(D);
1973 STORE(EA, 1, *rS);
1974 *rA = EA;
1975 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RS_BITMASK, 0);
1976
19770.31,6.RS,11.RA,16.RB,21.247,31./:X:::Store Byte with Update Indexed
1978*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1979*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1980*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1981*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1982 unsigned_word EA;
1983 if (RA_is_0)
1984 program_interrupt(processor, cia,
1985 illegal_instruction_program_interrupt);
1986 EA = *rA + *rB;
1987 STORE(EA, 1, *rS);
1988 *rA = EA;
1989 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RB_BITMASK | RS_BITMASK, 0);
1990
19910.44,6.RS,11.RA,16.D:D:::Store Half Word
1992*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
1993*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1994*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1995*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1996 unsigned_word b;
1997 unsigned_word EA;
1998 if (RA_is_0) b = 0;
1999 else b = *rA;
2000 EA = b + EXTS(D);
2001 STORE(EA, 2, *rS);
2002 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RS_BITMASK, 0);
2003
20040.31,6.RS,11.RA,16.RB,21.407,31./:X:::Store Half Word Indexed
2005*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2006*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2007*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2008*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2009 unsigned_word b;
2010 unsigned_word EA;
2011 if (RA_is_0) b = 0;
2012 else b = *rA;
2013 EA = b + *rB;
2014 STORE(EA, 2, *rS);
2015 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
2016
20170.45,6.RS,11.RA,16.D:D:::Store Half Word with Update
2018*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2019*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2020*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2021*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2022 unsigned_word EA;
2023 if (RA_is_0)
2024 program_interrupt(processor, cia,
2025 illegal_instruction_program_interrupt);
2026 EA = *rA + EXTS(D);
2027 STORE(EA, 2, *rS);
2028 *rA = EA;
2029 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RS_BITMASK, 0);
2030
20310.31,6.RS,11.RA,16.RB,21.439,31./:X:::Store Half Word with Update Indexed
2032*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2033*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2034*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2035*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2036 unsigned_word EA;
2037 if (RA_is_0)
2038 program_interrupt(processor, cia,
2039 illegal_instruction_program_interrupt);
2040 EA = *rA + *rB;
2041 STORE(EA, 2, *rS);
2042 *rA = EA;
2043 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RB_BITMASK | RS_BITMASK, 0);
2044
20450.36,6.RS,11.RA,16.D:D:::Store Word
2046*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2047*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2048*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2049*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2050 unsigned_word b;
2051 unsigned_word EA;
2052 if (RA_is_0) b = 0;
2053 else b = *rA;
2054 EA = b + EXTS(D);
2055 STORE(EA, 4, *rS);
2056 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RS_BITMASK, 0);
2057
20580.31,6.RS,11.RA,16.RB,21.151,31./:X:::Store Word Indexed
2059*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2060*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2061*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2062*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2063 unsigned_word b;
2064 unsigned_word EA;
2065 if (RA_is_0) b = 0;
2066 else b = *rA;
2067 EA = b + *rB;
2068 STORE(EA, 4, *rS);
2069 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
2070
20710.37,6.RS,11.RA,16.D:D:::Store Word with Update
2072*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2073*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2074*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2075*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2076 unsigned_word EA;
2077 if (RA_is_0)
2078 program_interrupt(processor, cia,
2079 illegal_instruction_program_interrupt);
2080 EA = *rA + EXTS(D);
2081 STORE(EA, 4, *rS);
2082 *rA = EA;
2083 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RS_BITMASK, 0);
2084
20850.31,6.RS,11.RA,16.RB,21.183,31./:X:::Store Word with Update Indexed
2086*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2087*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2088*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2089*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2090 unsigned_word EA;
2091 if (RA_is_0)
2092 program_interrupt(processor, cia,
2093 illegal_instruction_program_interrupt);
2094 EA = *rA + *rB;
2095 STORE(EA, 4, *rS);
2096 *rA = EA;
2097 PPC_INSN_INT(RA_BITMASK, RA_BITMASK | RB_BITMASK | RS_BITMASK, 0);
2098
20990.62,6.RS,11.RA,16.DS,30.0:DS:64::Store Doubleword
2100# unsigned_word b;
2101# unsigned_word EA;
2102# if (RA_is_0) b = 0;
2103# else b = *rA;
2104# EA = b + EXTS(DS_0b00);
2105# STORE(EA, 8, *rS);
21060.31,6.RS,11.RA,16.RB,21.149,31./:X:64::Store Doubleword Indexed
2107# unsigned_word b;
2108# unsigned_word EA;
2109# if (RA_is_0) b = 0;
2110# else b = *rA;
2111# EA = b + *rB;
2112# STORE(EA, 8, *rS);
21130.62,6.RS,11.RA,16.DS,30.1:DS:64::Store Doubleword with Update
2114# unsigned_word EA;
2115# if (RA_is_0)
2116# program_interrupt(processor, cia
2117# illegal_instruction_program_interrupt);
2118# EA = *rA + EXTS(DS_0b00);
2119# STORE(EA, 8, *rS);
2120# *rA = EA;
21210.31,6.RS,11.RA,16.RB,21.181,31./:X:64::Store Doubleword with Update Indexed
2122# unsigned_word EA;
2123# if (RA_is_0)
2124# program_interrupt(processor, cia
2125# illegal_instruction_program_interrupt);
2126# EA = *rA + *rB;
2127# STORE(EA, 8, *rS);
2128# *rA = EA;
2129
2130
2131#
2132# I.3.3.4 Fixed-Point Load and Store with Byte Reversal Instructions
2133#
2134
21350.31,6.RT,11.RA,16.RB,21.790,31./:X:::Load Halfword Byte-Reverse Indexed
2136*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2137*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2138*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2139*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2140 unsigned_word b;
2141 unsigned_word EA;
2142 if (RA_is_0) b = 0;
2143 else b = *rA;
2144 EA = b + *rB;
2145 *rT = SWAP_2(MEM(unsigned, EA, 2));
2146 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
2147
21480.31,6.RT,11.RA,16.RB,21.534,31./:X:::Load Word Byte-Reverse Indexed
2149*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2150*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2151*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2152*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2153 unsigned_word b;
2154 unsigned_word EA;
2155 if (RA_is_0) b = 0;
2156 else b = *rA;
2157 EA = b + *rB;
2158 *rT = SWAP_4(MEM(unsigned, EA, 4));
2159 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
2160
21610.31,6.RS,11.RA,16.RB,21.918,31./:X:::Store Half Word Byte-Reversed Indexed
2162*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2163*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2164*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2165*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2166 unsigned_word b;
2167 unsigned_word EA;
2168 if (RA_is_0) b = 0;
2169 else b = *rA;
2170 EA = b + *rB;
2171 STORE(EA, 2, SWAP_2(*rS));
2172 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
2173
21740.31,6.RS,11.RA,16.RB,21.662,31./:X:::Store Word Byte-Reversed Indexed
2175*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2176*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2177*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
2178*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2179 unsigned_word b;
2180 unsigned_word EA;
2181 if (RA_is_0) b = 0;
2182 else b = *rA;
2183 EA = b + *rB;
2184 STORE(EA, 4, SWAP_4(*rS));
2185 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 0);
2186
2187
2188#
2189# I.3.3.5 Fixed-Point Load and Store Multiple Instrctions
2190#
2191
21920.46,6.RT,11.RA,16.D:D:::Load Multiple Word
2193 unsigned_word EA;
2194 unsigned_word b;
2195 int r;
2196 if (RA_is_0) b = 0;
2197 else b = *rA;
2198 EA = b + EXTS(D);
2199 r = RT;
2200 if (RA >= r)
2201 program_interrupt(processor, cia,
2202 illegal_instruction_program_interrupt);
2203 if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT || (EA % 4 != 0))
2204 alignment_interrupt(processor, cia, EA);
2205 while (r <= 31) {
2206 GPR(r) = MEM(unsigned, EA, 4);
2207 r = r + 1;
2208 EA = EA + 4;
2209 }
2210
22110.47,6.RS,11.RA,16.D:D:::Store Multiple Word
2212 unsigned_word EA;
2213 unsigned_word b;
2214 int r;
2215 if (RA_is_0) b = 0;
2216 else b = *rA;
2217 EA = b + EXTS(D);
2218 if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT
2219 || (EA % 4 != 0))
2220 alignment_interrupt(processor, cia, EA);
2221 r = RS;
2222 while (r <= 31) {
2223 STORE(EA, 4, GPR(r));
2224 r = r + 1;
2225 EA = EA + 4;
2226 }
2227
2228
2229#
2230# I.3.3.6 Fixed-Point Move Assist Instructions
2231#
2232
22330.31,6.RT,11.RA,16.NB,21.597,31./:X:::Load String Word Immediate
2234 unsigned_word EA;
2235 int n;
2236 int r;
2237 int i;
2238 int nr;
2239 if (RA_is_0) EA = 0;
2240 else EA = *rA;
2241 if (NB == 0) n = 32;
2242 else n = NB;
2243 r = RT - 1;
2244 i = 32;
2245 nr = (n + 3) / 4;
2246 if ((RT + nr >= 32)
2247 ? (RA >= RT || RA < (RT + nr) % 32)
2248 : (RA >= RT && RA < RT + nr))
2249 program_interrupt(processor, cia,
2250 illegal_instruction_program_interrupt);
2251 if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
2252 alignment_interrupt(processor, cia, EA);
2253 while (n > 0) {
2254 if (i == 32) {
2255 r = (r + 1) % 32;
2256 GPR(r) = 0;
2257 }
2258 GPR(r) |= INSERTED(MEM(unsigned, EA, 1), i, i+7);
2259 if (i == 64) i = 32;
2260 EA = EA + 1;
2261 n = n - 1;
2262 }
2263
22640.31,6.RT,11.RA,16.RB,21.533,31./:X:::Load String Word Indexed
2265 unsigned_word EA;
2266 unsigned_word b;
2267 int n;
2268 int r;
2269 int i;
2270 int nr;
2271 if (RA_is_0) b = 0;
2272 else b = *rA;
2273 EA = b + *rB;
2274 n = EXTRACTED32(XER, 25, 31);
2275 r = RT - 1;
2276 i = 32;
2277 nr = (n + 3) / 4;
2278 if (((RT + n >= 32)
2279 ? ((RA >= RT || RA < (RT + n) % 32)
2280 || (RB >= RT || RB < (RT + n) % 32))
2281 : ((RA >= RT && RA < RT + n)
2282 || (RB >= RT && RB < RT + n)))
2283 || (RT == RA || RT == RB))
2284 program_interrupt(processor, cia,
2285 illegal_instruction_program_interrupt);
2286 if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
2287 alignment_interrupt(processor, cia, EA);
2288 while (n > 0) {
2289 if (i == 32) {
2290 r = (r + 1) % 32;
2291 GPR(i) = 0;
2292 }
2293 GPR(r) |= INSERTED(MEM(unsigned, EA, 1), i, i+7);
2294 i = i + 8;
2295 if (i == 64) i = 32;
2296 EA = EA + 1;
2297 n = n - 1;
2298 }
2299
23000.31,6.RS,11.RA,16.NB,21.725,31./:X:::Store String Word Immedate
2301 unsigned_word EA;
2302 int n;
2303 int r;
2304 int i;
2305 if (RA_is_0) EA = 0;
2306 else EA = *rA;
2307 if (NB == 0) n = 32;
2308 else n = NB;
2309 r = RS - 1;
2310 i = 32;
2311 if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
2312 alignment_interrupt(processor, cia, EA);
2313 while (n > 0) {
2314 if (i == 32) r = (r + 1) % 32;
2315 STORE(EA, 1, EXTRACTED(GPR(r), i, i+7));
2316 i = i + 8;
2317 if (i == 64) i = 32;
2318 EA = EA + 1;
2319 n = n - 1;
2320 }
2321
23220.31,6.RS,11.RA,16.RB,21.661,31./:X:::Store String Word Indexed
2323 unsigned_word EA;
2324 unsigned_word b;
2325 int n;
2326 int r;
2327 int i;
2328 if (RA_is_0) b = 0;
2329 else b = *rA;
2330 EA = b + *rB;
2331 if (CURRENT_ALIGNMENT == STRICT_ALIGNMENT)
2332 alignment_interrupt(processor, cia, EA);
2333 n = EXTRACTED32(XER, 25, 31);
2334 r = RS - 1;
2335 i = 32;
2336 while (n > 0) {
2337 if (i == 32) r = (r + 1) % 32;
2338 STORE(EA, 1, EXTRACTED(GPR(r), i, i+7));
2339 i = i + 8;
2340 if (i == 64) i = 32;
2341 EA = EA + 1;
2342 n = n - 1;
2343 }
2344
2345
2346#
2347# I.3.3.7 Storage Synchronization Instructions
2348#
2349# HACK: Rather than monitor addresses looking for a reason
2350# to cancel a reservation. This code instead keeps
2351# a copy of the data read from memory. Before performing
2352# a store, the memory area is checked to see if it has
2353# been changed.
23540.31,6.RT,11.RA,16.RB,21.20,31./:X:::Load Word And Reserve Indexed
2355*601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2356*603: PPC_UNIT_LSU, PPC_UNIT_IU, 1, 2, 0
2357*603e:PPC_UNIT_LSU, PPC_UNIT_IU, 1, 2, 0
2358*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
2359 unsigned_word b;
2360 unsigned_word EA;
2361 if (RA_is_0) b = 0;
2362 else b = *rA;
2363 EA = b + *rB;
2364 RESERVE = 1;
2365 RESERVE_ADDR = real_addr(EA, 1/*is-read?*/);
2366 RESERVE_DATA = MEM(unsigned, EA, 4);
2367 *rT = RESERVE_DATA;
2368 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
2369
23700.31,6.RT,11.RA,16.RB,21.84,31./:X:64::Load Doubleword And Reserve Indexed
2371 unsigned_word b;
2372 unsigned_word EA;
2373 if (RA_is_0) b = 0;
2374 else b = *rA;
2375 EA = b + *rB;
2376 RESERVE = 1;
2377 RESERVE_ADDR = real_addr(EA, 1/*is-read?*/);
2378 RESERVE_DATA = MEM(unsigned, EA, 8);
2379 *rT = RESERVE_DATA;
2380 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
2381
23820.31,6.RS,11.RA,16.RB,21.150,31.1:X:::Store Word Conditional Indexed
2383*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2384*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 8, 8, 0
2385*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 8, 8, 0
2386*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 3, 0
2387 unsigned_word b;
2388 unsigned_word EA;
2389 if (RA_is_0) b = 0;
2390 else b = *rA;
2391 EA = b + *rB;
2392 if (RESERVE) {
2393 if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/)
2394 && /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 4)) {
2395 STORE(EA, 4, *rS);
2396 CR_SET_XER_SO(0, cr_i_zero);
2397 }
2398 else {
2399 /* ment to randomly to store, we never do! */
2400 CR_SET_XER_SO(0, 0);
2401 }
2402 RESERVE = 0;
2403 }
2404 else {
2405 CR_SET_XER_SO(0, 0);
2406 }
2407 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 1/*Rc*/);
2408
24090.31,6.RS,11.RA,16.RB,21.214,31.1:X:64::Store Doubleword Conditional Indexed
2410 unsigned_word b;
2411 unsigned_word EA;
2412 if (RA_is_0) b = 0;
2413 else b = *rA;
2414 EA = b + *rB;
2415 if (RESERVE) {
2416 if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/)
2417 && /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 8)) {
2418 STORE(EA, 8, *rS);
2419 CR_SET_XER_SO(0, cr_i_zero);
2420 }
2421 else {
2422 /* ment to randomly to store, we never do */
2423 CR_SET_XER_SO(0, 0);
2424 }
2425 RESERVE = 0;
2426 }
2427 else {
2428 CR_SET_XER_SO(0, 0);
2429 }
2430 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK | RS_BITMASK, 1/*Rc*/);
2431
24320.31,6./,11./,16./,21.598,31./:X::sync:Synchronize
2433*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2434*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
2435*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
2436*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
2437 /* do nothing */
2438
2439
2440#
2441# I.3.3.9 Fixed-Point Arithmetic Instructions
2442#
2443
24440.14,6.RT,11.RA,16.SI:D:::Add Immediate
2445*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2446*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2447*603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2448*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2449 if (RA_is_0) *rT = EXTS(SI);
2450 else *rT = *rA + EXTS(SI);
2451 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rT, (long)*rT));
2452 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
2453
24540.15,6.RT,11.RA,16.SI:D:::Add Immediate Shifted
2455*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2456*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2457*603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2458*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2459 if (RA_is_0) *rT = EXTS(SI) << 16;
2460 else *rT = *rA + (EXTS(SI) << 16);
2461 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rT, (long)*rT));
2462 PPC_INSN_INT(RT_BITMASK, (RA_BITMASK & ~1), 0);
2463
24640.31,6.RT,11.RA,16.RB,21.OE,22.266,31.Rc:XO:::Add
2465*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2466*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2467*603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2468*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2469 ALU_BEGIN(*rA);
2470 ALU_ADD(*rB);
2471 ALU_END(*rT, 0/*CA*/, OE, Rc);
2472 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2473
24740.31,6.RT,11.RA,16.RB,21.OE,22.40,31.Rc:XO:::Subtract From
2475*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2476*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2477*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2478*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2479 ALU_BEGIN(*rA);
2480 ALU_NOT;
2481 ALU_ADD(*rB);
2482 ALU_ADD(1);
2483 ALU_END(*rT, 0/*CA*/, OE, Rc);
2484 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2485
24860.12,6.RT,11.RA,16.SI:D:::Add Immediate Carrying
2487*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2488*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2489*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2490*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2491 ALU_BEGIN(*rA);
2492 ALU_ADD(EXTS(SI));
2493 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
2494 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, 0/*Rc*/);
2495
24960.13,6.RT,11.RA,16.SI:D:::Add Immediate Carrying and Record
2497*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2498*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2499*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2500*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2501 ALU_BEGIN(*rA);
2502 ALU_ADD(EXTS(SI));
2503 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 1/*Rc*/);
2504 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, 1/*Rc*/);
2505
25060.8,6.RT,11.RA,16.SI:D:::Subtract From Immediate Carrying
2507*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2508*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2509*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2510*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2511 ALU_BEGIN(*rA);
2512 ALU_NOT;
2513 ALU_ADD(EXTS(SI));
2514 ALU_ADD(1);
2515 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
2516 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, 0/*Rc*/);
2517
25180.31,6.RT,11.RA,16.RB,21.OE,22.10,31.Rc:XO:::Add Carrying
2519*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2520*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2521*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2522*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2523 ALU_BEGIN(*rA);
2524 ALU_ADD(*rB);
2525 ALU_END(*rT, 1/*CA*/, OE, Rc);
2526 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2527
25280.31,6.RT,11.RA,16.RB,21.OE,22.8,31.Rc:XO:::Subtract From Carrying
2529*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2530*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2531*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2532*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2533 /* RT <- ~RA + RB + 1 === RT <- RB - RA */
2534 ALU_BEGIN(*rA);
2535 ALU_NOT;
2536 ALU_ADD(*rB);
2537 ALU_ADD(1);
2538 ALU_END(*rT, 1/*CA*/, OE, Rc);
2539 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2540
25410.31,6.RT,11.RA,16.RB,21.OE,22.138,31.Rc:XO:::Add Extended
2542*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2543*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2544*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2545*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2546 ALU_BEGIN(*rA);
2547 ALU_ADD(*rB);
2548 ALU_ADD_CA;
2549 ALU_END(*rT, 1/*CA*/, OE, Rc);
2550 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2551
25520.31,6.RT,11.RA,16.RB,21.OE,22.136,31.Rc:XO:::Subtract From Extended
2553*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2554*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2555*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2556*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2557 ALU_BEGIN(*rA);
2558 ALU_NOT;
2559 ALU_ADD(*rB);
2560 ALU_ADD_CA;
2561 ALU_END(*rT, 1/*CA*/, OE, Rc);
2562 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2563
25640.31,6.RT,11.RA,16./,21.OE,22.234,31.Rc:XO:::Add to Minus One Extended
2565*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2566*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2567*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2568*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2569 ALU_BEGIN(*rA);
2570 ALU_ADD_CA;
2571 ALU_ADD(-1);
2572 ALU_END(*rT, 1/*CA*/, OE, Rc);
2573 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2574
25750.31,6.RT,11.RA,16./,21.OE,22.232,31.Rc:XO:::Subtract From Minus One Extended
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 ALU_BEGIN(*rA);
2581 ALU_NOT;
2582 ALU_ADD_CA;
2583 ALU_ADD(-1);
2584 ALU_END(*rT, 1/*CA*/, OE, Rc);
2585 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2586
25870.31,6.RT,11.RA,16./,21.OE,22.202,31.Rc:XO::addze:Add to Zero Extended
2588*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2589*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2590*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2591*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2592 ALU_BEGIN(*rA);
2593 ALU_ADD_CA;
2594 ALU_END(*rT, 1/*CA*/, OE, Rc);
2595 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2596
25970.31,6.RT,11.RA,16./,21.OE,22.200,31.Rc:XO:::Subtract from Zero Extended
2598*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2599*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2600*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2601*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2602 ALU_BEGIN(*rA);
2603 ALU_NOT;
2604 ALU_ADD_CA;
2605 ALU_END(*rT, 1/*CA*/, OE, Rc);
2606 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2607
26080.31,6.RT,11.RA,16./,21.OE,22.104,31.Rc:XO:::Negate
2609*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2610*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2611*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2612*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2613 ALU_BEGIN(*rA);
2614 ALU_NOT;
2615 ALU_ADD(1);
2616 ALU_END(*rT,0/*CA*/,OE,Rc);
2617 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, Rc);
2618
26190.7,6.RT,11.RA,16.SI:D::mulli:Multiply Low Immediate
2620*601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2621*603: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
2622*603e:PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
2623*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
2624 signed_word prod = *rA * EXTS(SI);
2625 *rT = prod;
2626 PPC_INSN_INT(RT_BITMASK, RA_BITMASK, 0/*Rc*/);
2627
26280.31,6.RT,11.RA,16.RB,21.OE,22.233,31.Rc:D:64::Multiply Low Doubleword
2629
26300.31,6.RT,11.RA,16.RB,21.OE,22.235,31.Rc:XO::mullw:Multiply Low Word
2631*601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2632*603: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2633*603e:PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2634*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0
2635 signed64 a = (signed32)(*rA);
2636 signed64 b = (signed32)(*rB);
2637 signed64 prod = a * b;
2638 signed_word t = prod;
2639 *rT = *rA * *rB;
2640 if (t != prod && OE)
2641 XER |= (xer_overflow | xer_summary_overflow);
2642 CR0_COMPARE(t, 0, Rc);
2643 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2644
26450.31,6.RT,11.RA,16.RB,21./,22.73,31.Rc:XO:64::Multiply High Doubleword
2646
26470.31,6.RT,11.RA,16.RB,21./,22.75,31.Rc:XO::mulhw:Multiply High Word
2648*601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2649*603: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2650*603e:PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
2651*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0
2652 signed64 a = (signed32)(*rA);
2653 signed64 b = (signed32)(*rB);
2654 signed64 prod = a * b;
2655 signed_word t = EXTRACTED64(prod, 0, 31);
2656 *rT = t;
2657 CR0_COMPARE(t, 0, Rc);
2658 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2659
26600.31,6.RT,11.RA,16.RB,21./,22.9,31.Rc:XO:64::Multiply High Doubleword Unsigned
2661
26620.31,6.RT,11.RA,16.RB,21./,22.11,31.Rc:XO::mulhwu:Multiply High Word Unsigned
2663*601: PPC_UNIT_IU, PPC_UNIT_IU, 10, 10, 0
2664*603: PPC_UNIT_IU, PPC_UNIT_IU, 6, 6, 0
2665*603e:PPC_UNIT_IU, PPC_UNIT_IU, 6, 6, 0
2666*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0
2667 unsigned64 a = (unsigned32)(*rA);
2668 unsigned64 b = (unsigned32)(*rB);
2669 unsigned64 prod = a * b;
2670 signed_word t = EXTRACTED64(prod, 0, 31);
2671 *rT = t;
2672 CR0_COMPARE(t, 0, Rc);
2673 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2674
26750.31,6.RT,11.RA,16.RB,21.OE,22.489,31.Rc:XO:64::Divide Doubleword
2676
26770.31,6.RT,11.RA,16.RB,21.OE,22.491,31.Rc:XO::divw:Divide Word
2678*601: PPC_UNIT_IU, PPC_UNIT_IU, 36, 36, 0
2679*603: PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2680*603e:PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2681*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 20, 20, 0
2682 signed64 dividend = (signed32)(*rA);
2683 signed64 divisor = (signed32)(*rB);
2684 if (divisor == 0 /* nb 0x8000..0 is sign extended */
2685 || (dividend == 0x80000000 && divisor == -1)) {
2686 if (OE)
2687 XER |= (xer_overflow | xer_summary_overflow);
2688 CR0_COMPARE(0, 0, Rc);
2689 }
2690 else {
2691 signed64 quotent = dividend / divisor;
2692 *rT = quotent;
2693 CR0_COMPARE((signed_word)quotent, 0, Rc);
2694 }
2695 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2696
26970.31,6.RT,11.RA,16.RB,21.OE,22.457,31.Rc:XO:64::Divide Doubleword Unsigned
2698
26990.31,6.RT,11.RA,16.RB,21.OE,22.459,31.Rc:XO::divwu:Divide Word Unsigned
2700*601: PPC_UNIT_IU, PPC_UNIT_IU, 36, 36, 0
2701*603: PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2702*603e:PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
2703*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 20, 20, 0
2704 unsigned64 dividend = (unsigned32)(*rA);
2705 unsigned64 divisor = (unsigned32)(*rB);
2706 if (divisor == 0) {
2707 if (OE)
2708 XER |= (xer_overflow | xer_summary_overflow);
2709 CR0_COMPARE(0, 0, Rc);
2710 }
2711 else {
2712 unsigned64 quotent = dividend / divisor;
2713 *rT = quotent;
2714 CR0_COMPARE((signed_word)quotent, 0, Rc);
2715 }
2716 PPC_INSN_INT(RT_BITMASK, RA_BITMASK | RB_BITMASK, Rc);
2717
2718
2719#
2720# I.3.3.10 Fixed-Point Compare Instructions
2721#
2722
27230.11,6.BF,9./,10.L,11.RA,16.SI:D:::Compare Immediate
2724*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2725*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2726*603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2727*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2728 if (!is_64bit_mode && L)
2729 program_interrupt(processor, cia,
2730 illegal_instruction_program_interrupt);
2731 else {
2732 signed_word a;
2733 signed_word b = EXTS(SI);
2734 if (L == 0)
2735 a = EXTENDED(*rA);
2736 else
2737 a = *rA;
2738 CR_COMPARE(BF, a, b);
2739 }
2740 PPC_INSN_INT_CR(0, RA_BITMASK, BF_BITMASK);
2741
27420.31,6.BF,9./,10.L,11.RA,16.RB,21.0,31./:X:::Compare
2743*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2744*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2745*603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2746*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2747 if (!is_64bit_mode && L)
2748 program_interrupt(processor, cia,
2749 illegal_instruction_program_interrupt);
2750 else {
2751 signed_word a;
2752 signed_word b;
2753 if (L == 0) {
2754 a = EXTENDED(*rA);
2755 b = EXTENDED(*rB);
2756 }
2757 else {
2758 a = *rA;
2759 b = *rB;
2760 }
2761 CR_COMPARE(BF, a, b);
2762 }
2763 PPC_INSN_INT_CR(0, RA_BITMASK | RB_BITMASK, BF_BITMASK);
2764
27650.10,6.BF,9./,10.L,11.RA,16.UI:D:::Compare Logical Immediate
2766*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2767*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2768*603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2769*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2770 if (!is_64bit_mode && L)
2771 program_interrupt(processor, cia,
2772 illegal_instruction_program_interrupt);
2773 else {
2774 unsigned_word a;
2775 unsigned_word b = UI;
2776 if (L == 0)
2777 a = MASKED(*rA, 32, 63);
2778 else
2779 a = *rA;
2780 CR_COMPARE(BF, a, b);
2781 }
2782 PPC_INSN_INT_CR(0, RA_BITMASK, BF_BITMASK);
2783
27840.31,6.BF,9./,10.L,11.RA,16.RB,21.32,31./:X:::Compare Logical
2785*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2786*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2787*603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
2788*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2789 if (!is_64bit_mode && L)
2790 program_interrupt(processor, cia,
2791 illegal_instruction_program_interrupt);
2792 else {
2793 unsigned_word a;
2794 unsigned_word b;
2795 if (L == 0) {
2796 a = MASKED(*rA, 32, 63);
2797 b = MASKED(*rB, 32, 63);
2798 }
2799 else {
2800 a = *rA;
2801 b = *rB;
2802 }
2803 CR_COMPARE(BF, a, b);
2804 }
2805 PPC_INSN_INT_CR(0, RA_BITMASK | RB_BITMASK, BF_BITMASK);
2806
2807
2808#
2809# I.3.3.11 Fixed-Point Trap Instructions
2810#
2811
28120.2,6.TO,11.RA,16.SI:D:64::Trap Doubleword Immediate
2813 if (!is_64bit_mode)
2814 program_interrupt(processor, cia,
2815 illegal_instruction_program_interrupt);
2816 else {
2817 signed_word a = *rA;
2818 signed_word b = EXTS(SI);
2819 if ((a < b && TO{0})
2820 || (a > b && TO{1})
2821 || (a == b && TO{2})
2822 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2823 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2824 )
2825 program_interrupt(processor, cia,
2826 trap_program_interrupt);
2827 }
2828
28290.3,6.TO,11.RA,16.SI:D:::Trap Word Immediate
2830*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2831*603: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2832*603e:PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2833*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2834 signed_word a = EXTENDED(*rA);
2835 signed_word b = EXTS(SI);
2836 if ((a < b && TO{0})
2837 || (a > b && TO{1})
2838 || (a == b && TO{2})
2839 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2840 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2841 )
2842 program_interrupt(processor, cia,
2843 trap_program_interrupt);
2844
28450.31,6.TO,11.RA,16.RB,21.68,31./:X:64::Trap Doubleword
2846 if (!is_64bit_mode)
2847 program_interrupt(processor, cia,
2848 illegal_instruction_program_interrupt);
2849 else {
2850 signed_word a = *rA;
2851 signed_word b = *rB;
2852 if ((a < b && TO{0})
2853 || (a > b && TO{1})
2854 || (a == b && TO{2})
2855 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2856 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2857 )
2858 program_interrupt(processor, cia,
2859 trap_program_interrupt);
2860 }
2861
28620.31,6.TO,11.RA,16.RB,21.4,31./:X:::Trap Word
2863*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2864*603: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2865*603e:PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
2866*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2867 signed_word a = EXTENDED(*rA);
2868 signed_word b = EXTENDED(*rB);
2869 if (TO == 12 && rA == rB) {
2870 ITRACE(trace_breakpoint, ("breakpoint\n"));
2871 cpu_halt(processor, cia, was_trap, 0);
2872 }
2873 else if ((a < b && TO{0})
2874 || (a > b && TO{1})
2875 || (a == b && TO{2})
2876 || ((unsigned_word)a < (unsigned_word)b && TO{3})
2877 || ((unsigned_word)a > (unsigned_word)b && TO{4})
2878 )
2879 program_interrupt(processor, cia,
2880 trap_program_interrupt);
2881
2882#
2883# I.3.3.12 Fixed-Point Logical Instructions
2884#
2885
28860.28,6.RS,11.RA,16.UI:D:::AND Immediate
2887*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2888*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2889*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2890*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2891 *rA = *rS & UI;
2892 CR0_COMPARE(*rA, 0, 1/*Rc*/);
2893 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2894 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 1/*Rc*/);
2895
28960.29,6.RS,11.RA,16.UI:D:::AND Immediate Shifted
2897*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2898*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2899*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2900*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2901 *rA = *rS & (UI << 16);
2902 CR0_COMPARE(*rA, 0, 1/*Rc*/);
2903 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2904 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 1/*Rc*/);
2905
29060.24,6.RS,11.RA,16.UI:D:::OR Immediate
2907*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2908*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2909*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2910*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2911 *rA = *rS | UI;
2912 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2913 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 0/*Rc*/);
2914
29150.25,6.RS,11.RA,16.UI:D:::OR Immediate Shifted
2916*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2917*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2918*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2919*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2920 *rA = *rS | (UI << 16);
2921 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2922 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 0/*Rc*/);
2923
29240.26,6.RS,11.RA,16.UI:D:::XOR Immediate
2925*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2926*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2927*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2928*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2929 *rA = *rS ^ UI;
2930 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2931 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 0/*Rc*/);
2932
29330.27,6.RS,11.RA,16.UI:D:::XOR Immediate Shifted
2934*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2935*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2936*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2937*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2938 *rA = *rS ^ (UI << 16);
2939 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2940 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, 0/*Rc*/);
2941
29420.31,6.RS,11.RA,16.RB,21.28,31.Rc:X:::AND
2943*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2944*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2945*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2946*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2947 *rA = *rS & *rB;
2948 CR0_COMPARE(*rA, 0, Rc);
2949 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2950 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2951
29520.31,6.RS,11.RA,16.RB,21.444,31.Rc:X:::OR
2953*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2954*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2955*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2956*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2957 *rA = *rS | *rB;
2958 CR0_COMPARE(*rA, 0, Rc);
2959 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2960 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2961
29620.31,6.RS,11.RA,16.RB,21.316,31.Rc:X:::XOR
2963*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2964*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2965*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2966*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2967 *rA = *rS ^ *rB;
2968 CR0_COMPARE(*rA, 0, Rc);
2969 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2970 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2971
29720.31,6.RS,11.RA,16.RB,21.476,31.Rc:X:::NAND
2973*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2974*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2975*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2976*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2977 *rA = ~(*rS & *rB);
2978 CR0_COMPARE(*rA, 0, Rc);
2979 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2980 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2981
29820.31,6.RS,11.RA,16.RB,21.124,31.Rc:X:::NOR
2983*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2984*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2985*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2986*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2987 *rA = ~(*rS | *rB);
2988 CR0_COMPARE(*rA, 0, Rc);
2989 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
2990 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
2991
29920.31,6.RS,11.RA,16.RB,21.284,31.Rc:X:::Equivalent
2993*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2994*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2995*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
2996*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
2997 *rA = ~(*rS ^ *rB); /* A === B */
2998 CR0_COMPARE(*rA, 0, Rc);
2999 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3000 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
3001
30020.31,6.RS,11.RA,16.RB,21.60,31.Rc:X:::AND with Complement
3003*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3004*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3005*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3006*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3007 *rA = *rS & ~*rB;
3008 CR0_COMPARE(*rA, 0, Rc);
3009 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3010 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
3011
30120.31,6.RS,11.RA,16.RB,21.412,31.Rc:X:::OR with Complement
3013*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3014*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3015*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3016*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3017 *rA = *rS | ~*rB;
3018 CR0_COMPARE(*rA, 0, Rc);
3019 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3020 PPC_INSN_INT(RA_BITMASK, RS_BITMASK | RB_BITMASK, Rc);
3021
30220.31,6.RS,11.RA,16./,21.954,31.Rc:X::extsb:Extend Sign Byte
3023*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3024*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3025*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3026*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3027 *rA = (signed_word)(signed8)*rS;
3028 CR0_COMPARE(*rA, 0, Rc);
3029 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3030 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3031
30320.31,6.RS,11.RA,16./,21.922,31.Rc:X::extsh:Extend Sign Half Word
3033*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3034*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3035*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3036*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3037 *rA = (signed_word)(signed16)*rS;
3038 CR0_COMPARE(*rA, 0, Rc);
3039 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3040 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3041
30420.31,6.RS,11.RA,16./,21.986,31.Rc:X:64::Extend Sign Word
3043*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3044*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3045*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3046*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3047# *rA = (signed_word)(signed32)*rS;
3048# CR0_COMPARE(*rA, 0, Rc);
3049
30500.31,6.RS,11.RA,16./,21.58,31.Rc:X:64::Count Leading Zeros Doubleword
3051# int count = 0;
3052# unsigned64 mask = BIT64(0);
3053# unsigned64 source = *rS;
3054# while (!(source & mask) && mask != 0) {
3055# mask >>= 1;
3056# count++;
3057# }
3058# *rA = count;
3059# CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */
3060
30610.31,6.RS,11.RA,16./,21.26,31.Rc:X:::Count Leading Zeros Word
3062*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3063*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3064*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3065*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3066 int count = 0;
3067 unsigned32 mask = BIT32(0);
3068 unsigned32 source = *rS;
3069 while (!(source & mask) && mask != 0) {
3070 mask >>= 1;
3071 count++;
3072 }
3073 *rA = count;
3074 ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3075 CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */
3076
3077
3078#
3079# I.3.3.13 Fixed-Point Rotate and Shift Instructions
3080#
3081
30820.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
3083# long n = (sh_5 << 4) | sh_0_4;
3084# unsigned_word r = ROTL64(*rS, n);
3085# long b = (mb_5 << 4) | mb_0_4;
3086# unsigned_word m = MASK(b, 63);
3087# signed_word result = r & m;
3088# *rA = result;
3089# ITRACE(trace_alu, (" Result = %ld (0x%lx)\n", (long)*rA, (long)*rA));
3090# CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
3091
30920.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
3093# long n = (sh_5 << 4) | sh_0_4;
3094# unsigned_word r = ROTL64(*rS, n);
3095# long e = (me_5 << 4) | me_0_4;
3096# unsigned_word m = MASK(0, e);
3097# signed_word result = r & m;
3098# *rA = result;
3099# CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
3100
31010.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
3102# long n = (sh_5 << 4) | sh_0_4;
3103# unsigned_word r = ROTL64(*rS, n);
3104# long b = (mb_5 << 4) | mb_0_4;
3105# unsigned_word m = MASK(0, (64-n));
3106# signed_word result = r & m;
3107# *rA = result;
3108# CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
3109
31100.21,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M:::Rotate Left Word Immediate then AND with Mask
3111*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3112*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3113*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3114*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3115 long n = SH;
3116 unsigned32 s = *rS;
3117 unsigned32 r = ROTL32(s, n);
3118 unsigned32 m = MASK(MB+32, ME+32);
3119 signed_word result = r & m;
3120 *rA = result;
3121 CR0_COMPARE(result, 0, Rc);
3122 ITRACE(trace_alu,
3123 ("n=%ld, s=0x%lx, r=0x%lx, m=0x%lx, result=0x%lx, cr=0x%lx\n",
3124 n, (unsigned long)s, (unsigned long)r, (unsigned long)m,
3125 (unsigned long)result, (unsigned long)CR));
3126 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3127
31280.30,6.RS,11.RA,16.RB,21.mb,27.8,31.Rc:MDS:64::Rotate Left Doubleword then Clear Left
3129# long n = MASKED(*rB, 58, 63);
3130# unsigned_word r = ROTL64(*rS, n);
3131# long b = (mb_5 << 4) | mb_0_4;
3132# unsigned_word m = MASK(b, 63);
3133# signed_word result = r & m;
3134# *rA = result;
3135# CR0_COMPARE(result, 0, Rc);
3136
31370.30,6.RS,11.RA,16.RB,21.me,27.9,31.Rc:MDS:64::Rotate Left Doubleword then Clear Right
3138# long n = MASKED(*rB, 58, 63);
3139# unsigned_word r = ROTL64(*rS, n);
3140# long e = (me_5 << 4) | me_0_4;
3141# unsigned_word m = MASK(0, e);
3142# signed_word result = r & m;
3143# *rA = result;
3144# CR0_COMPARE(result, 0, Rc);
3145
31460.23,6.RS,11.RA,16.RB,21.MB,26.ME,31.Rc:M:::Rotate Left Word then AND with Mask
3147 long n = MASKED(*rB, 59, 63);
3148 unsigned32 r = ROTL32(*rS, n);
3149 unsigned32 m = MASK(MB+32, ME+32);
3150 signed_word result = r & m;
3151 *rA = result;
3152 CR0_COMPARE(result, 0, Rc);
3153
31540.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
3155# long n = (sh_5 << 4) | sh_0_4;
3156# unsigned_word r = ROTL64(*rS, n);
3157# long b = (mb_5 << 4) | mb_0_4;
3158# unsigned_word m = MASK(b, (64-n));
3159# signed_word result = (r & m) | (*rA & ~m)
3160# *rA = result;
3161# CR0_COMPARE(result, 0, Rc);
3162
31630.20,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M::rlwimi:Rotate Left Word Immediate then Mask Insert
3164*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3165*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3166*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3167*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3168 long n = SH;
3169 unsigned32 r = ROTL32(*rS, n);
3170 unsigned32 m = MASK(MB+32, ME+32);
3171 signed_word result = (r & m) | (*rA & ~m);
3172 *rA = result;
3173 ITRACE(trace_alu, (": n=%ld *rS=0x%lx r=0x%lx m=0x%lx result=0x%lx\n",
3174 n, (unsigned long)*rS, (unsigned long)r, (unsigned long)m,
3175 (unsigned long)result));
3176 CR0_COMPARE(result, 0, Rc);
3177 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3178
3179
31800.31,6.RS,11.RA,16.RB,21.27,31.Rc:X:64::Shift Left Doubleword
3181
31820.31,6.RS,11.RA,16.RB,21.24,31.Rc:X:::Shift Left Word
3183*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3184*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3185*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3186*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3187 int n = MASKED(*rB, 58, 63);
3188 unsigned32 source = *rS;
3189 signed_word shifted;
3190 if (n < 32)
3191 shifted = (source << n);
3192 else
3193 shifted = 0;
3194 *rA = shifted;
3195 CR0_COMPARE(shifted, 0, Rc);
3196 ITRACE(trace_alu,
3197 ("n=%d, source=0x%lx, shifted=0x%lx\n",
3198 n, (unsigned long)source, (unsigned long)shifted));
3199 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3200
32010.31,6.RS,11.RA,16.RB,21.539,31.Rc:X:64::Shift Right Doubleword
3202
32030.31,6.RS,11.RA,16.RB,21.536,31.Rc:X:::Shift Right Word
3204*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3205*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3206*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3207*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3208 int n = MASKED(*rB, 58, 63);
3209 unsigned32 source = *rS;
3210 signed_word shifted;
3211 if (n < 32)
3212 shifted = (source >> n);
3213 else
3214 shifted = 0;
3215 *rA = shifted;
3216 CR0_COMPARE(shifted, 0, Rc);
3217 ITRACE(trace_alu, \
3218 ("n=%d, source=0x%lx, shifted=0x%lx\n",
3219 n, (unsigned long)source, (unsigned long)shifted));
3220 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3221
32220.31,6.RS,11.RA,16.sh_0_4,21.413,30.sh_5,31.Rc:XS:64::Shift Right Algebraic Doubleword Immediate
3223
32240.31,6.RS,11.RA,16.SH,21.824,31.Rc:X:::Shift Right Algebraic Word Immediate
3225*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3226*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3227*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3228*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3229 int n = SH;
3230 signed_word r = ROTL32(*rS, /*64*/32-n);
3231 signed_word m = MASK(n+32, 63);
3232 int S = MASKED(*rS, 32, 32);
3233 signed_word shifted = (r & m) | (S ? ~m : 0);
3234 *rA = shifted;
3235 if (S && ((r & ~m) & MASK(32, 63)) != 0)
3236 XER |= xer_carry;
3237 else
3238 XER &= ~xer_carry;
3239 CR0_COMPARE(shifted, 0, Rc);
3240 ITRACE(trace_alu, (" Result = %ld (0x%lx), XER = %ld\n",
3241 (long)*rA, (long)*rA, (long)XER));
3242 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3243
32440.31,6.RS,11.RA,16.RB,21.794,31.Rc:X:64::Shift Right Algebraic Doubleword
3245
32460.31,6.RS,11.RA,16.RB,21.792,31.Rc:X:::Shift Right Algebraic Word
3247*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3248*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3249*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3250*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
3251 unsigned64 mask;
3252 int n = MASKED(*rB, 59, 63);
3253 signed32 source = (signed32)*rS; /* signed to keep sign bit */
3254 signed32 shifted = source >> n;
3255 int S = (MASKED(*rS,32,32) != 0);
3256 signed64 r = ((unsigned64) source);
3257 r = ((unsigned64) source) << 32 | (unsigned32) source;
3258 r = ROTL64(r,64-n);
3259 if (MASKED(*rB,58,58) == 0)
3260 mask = (unsigned64) MASK64(n+32,63);
3261 else
3262 mask = (unsigned64) 0;
3263 *rA = (signed_word) (r & mask | ((signed64) -1*S) & ~mask); /* if 64bit will sign extend */
3264 if (S && (MASKED(r & ~mask,32,63)!=0))
3265 XER |= xer_carry;
3266 else
3267 XER &= ~xer_carry;
3268 CR0_COMPARE(*rA, 0, Rc);
3269 ITRACE(trace_alu, (" Result = %ld (0x%lx), XER = %ld\n",
3270 (long)*rA, (long)*rA, (long)XER));
3271 PPC_INSN_INT(RA_BITMASK, RS_BITMASK, Rc);
3272
3273#
3274# I.3.3.14 Move to/from System Register Instructions
3275#
3276
32770.31,6.RS,11.SPR,21.467,31./:XFX::mtspr %SPR, %RS:Move to Special Purpose Register
3278*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3279*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
3280*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
3281*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
3282 int n = (SPR{5:9} << 5) | SPR{0:4};
3283 if (SPR{0} && IS_PROBLEM_STATE(processor))
3284 program_interrupt(processor, cia,
3285 privileged_instruction_program_interrupt);
3286 else if (!spr_is_valid(n)
3287 || spr_is_readonly(n))
3288 program_interrupt(processor, cia,
3289 illegal_instruction_program_interrupt);
3290 else {
3291 spreg new_val = (spr_length(n) == 64
3292 ? *rS
3293 : MASKED(*rS, 32, 63));
3294 /* HACK - time base registers need to be updated immediatly */
3295 if (WITH_TIME_BASE) {
3296 switch (n) {
3297 case spr_tbu:
3298 cpu_set_time_base(processor,
3299 (MASKED64(cpu_get_time_base(processor), 32, 63)
3300 | INSERTED64(new_val, 0, 31)));
3301 break;
3302 case spr_tbl:
3303 cpu_set_time_base(processor,
3304 (MASKED64(cpu_get_time_base(processor), 0, 31)
3305 | INSERTED64(new_val, 32, 63)));
3306 break;
3307 case spr_dec:
3308 cpu_set_decrementer(processor, new_val);
3309 break;
3310 default:
3311 SPREG(n) = new_val;
3312 break;
3313 }
3314 }
3315 else {
3316 SPREG(n) = new_val;
3317 }
3318 }
3319 PPC_INSN_TO_SPR(RS_BITMASK, n);
3320
33210.31,6.RT,11.SPR,21.339,31./:XFX::mfspr %RT, %SPR:Move from Special Purpose Register
3322*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3323*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3324*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3325*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
3326 int n = (SPR{5:9} << 5) | SPR{0:4};
3327 if (SPR{0} && IS_PROBLEM_STATE(processor))
3328 program_interrupt(processor, cia,
3329 privileged_instruction_program_interrupt);
3330 else if (!spr_is_valid(n))
3331 program_interrupt(processor, cia,
3332 illegal_instruction_program_interrupt);
3333 else {
3334 /* HACK - time base registers need to be calculated */
3335 if (WITH_TIME_BASE) {
3336 switch (n) {
3337 case spr_dec:
3338 *rT = cpu_get_decrementer(processor);
3339 break;
3340 case spr_tbu:
3341 case spr_tbl:
3342 /* NOTE - these SPR's are not readable. Use mftb[ul] */
3343 default:
3344 *rT = SPREG(n);
3345 break;
3346 }
3347 }
3348 else {
3349 *rT = SPREG(n);
3350 }
3351 }
3352 PPC_INSN_FROM_SPR(RT_BITMASK, n);
3353
33540.31,6.RS,11./,12.FXM,20./,21.144,31./:XFX::mtfcr:Move to Condition Register Fields
3355*601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
3356*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3357*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3358*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
3359 if (FXM == 0xff) {
3360 CR = *rS;
3361 }
3362 else {
3363 unsigned_word mask = 0;
3364 unsigned_word f;
3365 for (f = 0; f < 8; f++) {
3366 if (FXM & (0x80 >> f))
3367 mask |= (0xf << 4*(7-f));
3368 }
3369 CR = (MASKED(*rS, 32, 63) & mask) | (CR & ~mask);
3370 }
3371 PPC_INSN_MTCR(RS_BITMASK, FXM);
3372
33730.31,6.BF,9./,11./,16./,21.512,31./:X:::Move to Condition Register from XER
3374# CR_SET(BF, EXTRACTED32(XER, 0, 3));
3375# MBLIT32(XER, 0, 3, 0);
3376
33770.31,6.RT,11./,16./,21.19,31./:X:::Move From Condition Register
3378*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3379*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3380*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
3381*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
3382 *rT = (unsigned32)CR;
3383 PPC_INSN_MFCR(RT_BITMASK);
3384
3385#
3386# I.4.6.2 Floating-Point Load Instructions
3387#
3388
33890.48,6.FRT,11.RA,16.D:D:f:lfs:Load Floating-Point Single
3390*601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3391*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3392*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3393*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3394 unsigned_word b;
3395 unsigned_word EA;
3396 if (RA_is_0) b = 0;
3397 else b = *rA;
3398 EA = b + EXTS(D);
3399 *frT = DOUBLE(MEM(unsigned, EA, 4));
3400 PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3401
34020.31,6.FRT,11.RA,16.RB,21.535,31./:X:f::Load Floating-Point Single Indexed
3403*601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3404*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3405*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3406*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3407 unsigned_word b;
3408 unsigned_word EA;
3409 if (RA_is_0) b = 0;
3410 else b = *rA;
3411 EA = b + *rB;
3412 *frT = DOUBLE(MEM(unsigned, EA, 4));
3413 PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3414
34150.49,6.FRT,11.RA,16.D:D:f::Load Floating-Point Single with Update
3416*601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3417*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3418*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3419*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3420 unsigned_word EA;
3421 if (RA_is_0)
3422 program_interrupt(processor, cia,
3423 illegal_instruction_program_interrupt);
3424 EA = *rA + EXTS(D);
3425 *frT = DOUBLE(MEM(unsigned, EA, 4));
3426 *rA = EA;
3427 PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3428
34290.31,6.FRT,11.RA,16.RB,21.576,31./:X:f::Load Floating-Point Single with Update Indexed
3430*601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3431*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3432*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3433*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3434 unsigned_word EA;
3435 if (RA_is_0)
3436 program_interrupt(processor, cia,
3437 illegal_instruction_program_interrupt);
3438 EA = *rA + *rB;
3439 *frT = DOUBLE(MEM(unsigned, EA, 4));
3440 *rA = EA;
3441 PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3442
34430.50,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double
3444*601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3445*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3446*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3447*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3448 unsigned_word b;
3449 unsigned_word EA;
3450 if (RA_is_0) b = 0;
3451 else b = *rA;
3452 EA = b + EXTS(D);
3453 *frT = MEM(unsigned, EA, 8);
3454 PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3455
34560.31,6.FRT,11.RA,16.RB,21.599,31./:X:f::Load Floating-Point Double Indexed
3457*601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3458*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3459*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3460*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3461 unsigned_word b;
3462 unsigned_word EA;
3463 if (RA_is_0) b = 0;
3464 else b = *rA;
3465 EA = b + *rB;
3466 *frT = MEM(unsigned, EA, 8);
3467 PPC_INSN_INT_FLOAT(0, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3468
34690.51,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double with Update
3470*601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3471*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3472*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3473*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3474 unsigned_word EA;
3475 if (RA_is_0)
3476 program_interrupt(processor, cia,
3477 illegal_instruction_program_interrupt);
3478 EA = *rA + EXTS(D);
3479 *frT = MEM(unsigned, EA, 8);
3480 *rA = EA;
3481 PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1), 0);
3482
34830.31,6.FRT,11.RA,16.RB,21.631,31./:X:f::Load Floating-Point Double with Update Indexed
3484*601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
3485*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3486*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3487*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3488 unsigned_word EA;
3489 if (RA_is_0)
3490 program_interrupt(processor, cia,
3491 illegal_instruction_program_interrupt);
3492 EA = *rA + *rB;
3493 *frT = MEM(unsigned, EA, 8);
3494 *rA = EA;
3495 PPC_INSN_INT_FLOAT(RA_BITMASK, FRT_BITMASK, (RA_BITMASK & ~1) | RB_BITMASK, 0);
3496
3497
3498#
3499# I.4.6.3 Floating-Point Store Instructions
3500#
3501
35020.52,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single
3503*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3504*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3505*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3506*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3507 unsigned_word b;
3508 unsigned_word EA;
3509 if (RA_is_0) b = 0;
3510 else b = *rA;
3511 EA = b + EXTS(D);
3512 STORE(EA, 4, SINGLE(*frS));
3513 PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3514
35150.31,6.FRS,11.RA,16.RB,21.663,31./:X:f::Store Floating-Point Single Indexed
3516*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3517*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3518*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3519*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3520 unsigned_word b;
3521 unsigned_word EA;
3522 if (RA_is_0) b = 0;
3523 else b = *rA;
3524 EA = b + *rB;
3525 STORE(EA, 4, SINGLE(*frS));
3526 PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3527
35280.53,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single with Update
3529*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3530*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3531*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3532*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3533 unsigned_word EA;
3534 if (RA_is_0)
3535 program_interrupt(processor, cia,
3536 illegal_instruction_program_interrupt);
3537 EA = *rA + EXTS(D);
3538 STORE(EA, 4, SINGLE(*frS));
3539 *rA = EA;
3540 PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3541
35420.31,6.FRS,11.RA,16.RB,21.695,31./:X:f::Store Floating-Point Single with Update Indexed
3543*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3544*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3545*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3546*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3547 unsigned_word EA;
3548 if (RA_is_0)
3549 program_interrupt(processor, cia,
3550 illegal_instruction_program_interrupt);
3551 EA = *rA + *rB;
3552 STORE(EA, 4, SINGLE(*frS));
3553 *rA = EA;
3554 PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3555
35560.54,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double
3557*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3558*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3559*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3560*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3561 unsigned_word b;
3562 unsigned_word EA;
3563 if (RA_is_0) b = 0;
3564 else b = *rA;
3565 EA = b + EXTS(D);
3566 STORE(EA, 8, *frS);
3567 PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3568
35690.31,6.FRS,11.RA,16.RB,21.727,31./:X:f::Store Floating-Point Double Indexed
3570*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3571*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3572*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3573*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3574 unsigned_word b;
3575 unsigned_word EA;
3576 if (RA_is_0) b = 0;
3577 else b = *rA;
3578 EA = b + *rB;
3579 STORE(EA, 8, *frS);
3580 PPC_INSN_INT_FLOAT(0, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3581
35820.55,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double with Update
3583*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3584*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3585*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3586*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3587 unsigned_word EA;
3588 if (RA_is_0)
3589 program_interrupt(processor, cia,
3590 illegal_instruction_program_interrupt);
3591 EA = *rA + EXTS(D);
3592 STORE(EA, 8, *frS);
3593 *rA = EA;
3594 PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1), FRS_BITMASK);
3595
35960.31,6.FRS,11.RA,16.RB,21.759,31./:X:f::Store Floating-Point Double with Update Indexed
3597*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
3598*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3599*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
3600*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
3601 unsigned_word EA;
3602 if (RA_is_0)
3603 program_interrupt(processor, cia,
3604 illegal_instruction_program_interrupt);
3605 EA = *rA + *rB;
3606 STORE(EA, 8, *frS);
3607 *rA = EA;
3608 PPC_INSN_INT_FLOAT(RA_BITMASK, 0, (RA_BITMASK & ~1) | RB_BITMASK, FRS_BITMASK);
3609
3610
3611#
3612# I.4.6.4 Floating-Point Move Instructions
3613#
3614
36150.63,6.FRT,11./,16.FRB,21.72,31.Rc:X:f::Floating Move Register
3616*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3617*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3618*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3619*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3620 *frT = *frB;
3621 CR1_UPDATE(Rc);
3622 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3623
36240.63,6.FRT,11./,16.FRB,21.40,31.Rc:X:f::Floating Negate
3625*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3626*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3627*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3628*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3629 *frT = *frB ^ BIT64(0);
3630 CR1_UPDATE(Rc);
3631 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3632
36330.63,6.FRT,11./,16.FRB,21.264,31.Rc:X:f::Floating Absolute Value
3634*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3635*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3636*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3637*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3638 *frT = *frB & ~BIT64(0);
3639 CR1_UPDATE(Rc);
3640 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3641
36420.63,6.FRT,11./,16.FRB,21.136,31.Rc:X:f::Floating Negative Absolute Value
3643*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3644*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3645*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3646*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3647 *frT = *frB | BIT64(0);
3648 CR1_UPDATE(Rc);
3649 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
3650
3651
3652#
3653# I.4.6.5 Floating-Point Arithmetic Instructions
3654#
3655
36560.63,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadd:Floating Add
3657*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3658*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3659*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3660*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3661 FPSCR_BEGIN;
3662 if (is_invalid_operation(processor, cia,
3663 *frA, *frB,
3664 fpscr_vxsnan | fpscr_vxisi,
3665 0, /*single?*/
3666 0) /*negate?*/) {
3667 invalid_arithemetic_operation(processor, cia,
3668 frT, *frA, *frB, 0,
3669 0, /*instruction_is_frsp*/
3670 0, /*instruction_is_convert_to_64bit*/
3671 0, /*instruction_is_convert_to_32bit*/
3672 0); /*single-precision*/
3673 }
3674 else {
3675 /*HACK!*/
3676 double s = *(double*)frA + *(double*)frB;
3677 *(double*)frT = s;
3678 }
3679 FPSCR_END(Rc);
3680 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3681
36820.59,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadds:Floating Add Single
3683*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3684*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3685*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3686*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3687 FPSCR_BEGIN;
3688 if (is_invalid_operation(processor, cia,
3689 *frA, *frB,
3690 fpscr_vxsnan | fpscr_vxisi,
3691 1, /*single?*/
3692 0) /*negate?*/) {
3693 invalid_arithemetic_operation(processor, cia,
3694 frT, *frA, *frB, 0,
3695 0, /*instruction_is_frsp*/
3696 0, /*instruction_is_convert_to_64bit*/
3697 0, /*instruction_is_convert_to_32bit*/
3698 1); /*single-precision*/
3699 }
3700 else {
3701 /*HACK!*/
3702 float s = *(double*)frA + *(double*)frB;
3703 *(double*)frT = s;
3704 }
3705 FPSCR_END(Rc);
3706 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3707
37080.63,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsub:Floating Subtract
3709*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3710*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3711*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3712*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3713 FPSCR_BEGIN;
3714 if (is_invalid_operation(processor, cia,
3715 *frA, *frB,
3716 fpscr_vxsnan | fpscr_vxisi,
3717 0, /*single?*/
3718 1) /*negate?*/) {
3719 invalid_arithemetic_operation(processor, cia,
3720 frT, *frA, *frB, 0,
3721 0, /*instruction_is_frsp*/
3722 0, /*instruction_is_convert_to_64bit*/
3723 0, /*instruction_is_convert_to_32bit*/
3724 0); /*single-precision*/
3725 }
3726 else {
3727 /*HACK!*/
3728 double s = *(double*)frA - *(double*)frB;
3729 *(double*)frT = s;
3730 }
3731 FPSCR_END(Rc);
3732 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3733
37340.59,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsubs:Floating Subtract Single
3735*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3736*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3737*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3738*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3739 FPSCR_BEGIN;
3740 if (is_invalid_operation(processor, cia,
3741 *frA, *frB,
3742 fpscr_vxsnan | fpscr_vxisi,
3743 1, /*single?*/
3744 1) /*negate?*/) {
3745 invalid_arithemetic_operation(processor, cia,
3746 frT, *frA, *frB, 0,
3747 0, /*instruction_is_frsp*/
3748 0, /*instruction_is_convert_to_64bit*/
3749 0, /*instruction_is_convert_to_32bit*/
3750 1); /*single-precision*/
3751 }
3752 else {
3753 /*HACK!*/
3754 float s = *(double*)frA - *(double*)frB;
3755 *(double*)frT = s;
3756 }
3757 FPSCR_END(Rc);
3758 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3759
37600.63,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmul:Floating Multiply
3761*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3762*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3763*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3764*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3765 FPSCR_BEGIN;
3766 if (is_invalid_operation(processor, cia,
3767 *frA, *frC,
3768 fpscr_vxsnan | fpscr_vximz,
3769 0, /*single?*/
3770 0) /*negate?*/) {
3771 invalid_arithemetic_operation(processor, cia,
3772 frT, *frA, 0, *frC,
3773 0, /*instruction_is_frsp*/
3774 0, /*instruction_is_convert_to_64bit*/
3775 0, /*instruction_is_convert_to_32bit*/
3776 0); /*single-precision*/
3777 }
3778 else {
3779 /*HACK!*/
3780 double s = *(double*)frA * *(double*)frC;
3781 *(double*)frT = s;
3782 }
3783 FPSCR_END(Rc);
3784 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRC_BITMASK, Rc);
3785
37860.59,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmuls:Floating Multiply Single
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 if (is_invalid_operation(processor, cia,
3793 *frA, *frC,
3794 fpscr_vxsnan | fpscr_vximz,
3795 1, /*single?*/
3796 0) /*negate?*/) {
3797 invalid_arithemetic_operation(processor, cia,
3798 frT, *frA, 0, *frC,
3799 0, /*instruction_is_frsp*/
3800 0, /*instruction_is_convert_to_64bit*/
3801 0, /*instruction_is_convert_to_32bit*/
3802 1); /*single-precision*/
3803 }
3804 else {
3805 /*HACK!*/
3806 float s = *(double*)frA * *(double*)frC;
3807 *(double*)frT = s;
3808 }
3809 FPSCR_END(Rc);
3810 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRC_BITMASK, Rc);
3811
38120.63,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdiv:Floating Divide
3813*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 31, 31, 0
3814*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 33, 33, 0
3815*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 33, 33, 0
3816*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 32, 32, 0
3817 FPSCR_BEGIN;
3818 if (is_invalid_operation(processor, cia,
3819 *frA, *frB,
3820 fpscr_vxsnan | fpscr_vxzdz,
3821 0, /*single?*/
3822 0) /*negate?*/) {
3823 invalid_arithemetic_operation(processor, cia,
3824 frT, *frA, *frB, 0,
3825 0, /*instruction_is_frsp*/
3826 0, /*instruction_is_convert_to_64bit*/
3827 0, /*instruction_is_convert_to_32bit*/
3828 0); /*single-precision*/
3829 }
3830 else if (is_invalid_zero_divide (processor, cia,
3831 *frA, *frB,
3832 0 /*single?*/)) {
3833 invalid_zero_divide_operation (processor, cia,
3834 frT, *frA, *frB,
3835 0 /*single?*/);
3836 }
3837 else {
3838 /*HACK!*/
3839 double s = *(double*)frA / *(double*)frB;
3840 *(double*)frT = s;
3841 }
3842 FPSCR_END(Rc);
3843 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3844
38450.59,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdivs:Floating Divide Single
3846*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 17, 17, 0
3847*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0
3848*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0
3849*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0
3850 FPSCR_BEGIN;
3851 if (is_invalid_operation(processor, cia,
3852 *frA, *frB,
3853 fpscr_vxsnan | fpscr_vxzdz,
3854 1, /*single?*/
3855 0) /*negate?*/) {
3856 invalid_arithemetic_operation(processor, cia,
3857 frT, *frA, *frB, 0,
3858 0, /*instruction_is_frsp*/
3859 0, /*instruction_is_convert_to_64bit*/
3860 0, /*instruction_is_convert_to_32bit*/
3861 1); /*single-precision*/
3862 }
3863 else if (is_invalid_zero_divide (processor, cia,
3864 *frA, *frB,
3865 1 /*single?*/)) {
3866 invalid_zero_divide_operation (processor, cia,
3867 frT, *frA, *frB,
3868 1 /*single?*/);
3869 }
3870 else {
3871 /*HACK!*/
3872 float s = *(double*)frA / *(double*)frB;
3873 *(double*)frT = s;
3874 }
3875 FPSCR_END(Rc);
3876 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK, Rc);
3877
38780.63,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f:fmadd:Floating Multiply-Add
3879*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3880*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3881*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3882*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3883 FPSCR_BEGIN;
3884 double product; /*HACK! - incorrectly loosing precision ... */
3885 /* compute the multiply */
3886 if (is_invalid_operation(processor, cia,
3887 *frA, *frC,
3888 fpscr_vxsnan | fpscr_vximz,
3889 0, /*single?*/
3890 0) /*negate?*/) {
3891 invalid_arithemetic_operation(processor, cia,
3892 (unsigned64*)&product, *frA, 0, *frC,
3893 0, /*instruction_is_frsp*/
3894 0, /*instruction_is_convert_to_64bit*/
3895 0, /*instruction_is_convert_to_32bit*/
3896 0); /*single-precision*/
3897 }
3898 else {
3899 /*HACK!*/
3900 product = *(double*)frA * *(double*)frC;
3901 }
3902 /* compute the add */
3903 if (is_invalid_operation(processor, cia,
3904 product, *frB,
3905 fpscr_vxsnan | fpscr_vxisi,
3906 0, /*single?*/
3907 0) /*negate?*/) {
3908 invalid_arithemetic_operation(processor, cia,
3909 frT, product, *frB, 0,
3910 0, /*instruction_is_frsp*/
3911 0, /*instruction_is_convert_to_64bit*/
3912 0, /*instruction_is_convert_to_32bit*/
3913 0); /*single-precision*/
3914 }
3915 else {
3916 /*HACK!*/
3917 double s = product + *(double*)frB;
3918 *(double*)frT = s;
3919 }
3920 FPSCR_END(Rc);
3921 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
3922
39230.59,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f::Floating Multiply-Add Single
3924*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
3925*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3926*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3927*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3928 FPSCR_BEGIN;
3929 float product; /*HACK! - incorrectly loosing precision ... */
3930 /* compute the multiply */
3931 if (is_invalid_operation(processor, cia,
3932 *frA, *frC,
3933 fpscr_vxsnan | fpscr_vximz,
3934 1, /*single?*/
3935 0) /*negate?*/) {
3936 invalid_arithemetic_operation(processor, cia,
3937 (unsigned64*)&product, *frA, 0, *frC,
3938 0, /*instruction_is_frsp*/
3939 0, /*instruction_is_convert_to_64bit*/
3940 0, /*instruction_is_convert_to_32bit*/
3941 0); /*single-precision*/
3942 }
3943 else {
3944 /*HACK!*/
3945 product = *(double*)frA * *(double*)frC;
3946 }
3947 /* compute the add */
3948 if (is_invalid_operation(processor, cia,
3949 product, *frB,
3950 fpscr_vxsnan | fpscr_vxisi,
3951 1, /*single?*/
3952 0) /*negate?*/) {
3953 invalid_arithemetic_operation(processor, cia,
3954 frT, product, *frB, 0,
3955 0, /*instruction_is_frsp*/
3956 0, /*instruction_is_convert_to_64bit*/
3957 0, /*instruction_is_convert_to_32bit*/
3958 0); /*single-precision*/
3959 }
3960 else {
3961 /*HACK!*/
3962 float s = product + *(double*)frB;
3963 *(double*)frT = (double)s;
3964 }
3965 FPSCR_END(Rc);
3966 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
3967
39680.63,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract
3969*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
3970*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3971*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
3972*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
3973 FPSCR_BEGIN;
3974 double product; /*HACK! - incorrectly loosing precision ... */
3975 /* compute the multiply */
3976 if (is_invalid_operation(processor, cia,
3977 *frA, *frC,
3978 fpscr_vxsnan | fpscr_vximz,
3979 0, /*single?*/
3980 0) /*negate?*/) {
3981 invalid_arithemetic_operation(processor, cia,
3982 (unsigned64*)&product, *frA, 0, *frC,
3983 0, /*instruction_is_frsp*/
3984 0, /*instruction_is_convert_to_64bit*/
3985 0, /*instruction_is_convert_to_32bit*/
3986 0); /*single-precision*/
3987 }
3988 else {
3989 /*HACK!*/
3990 product = *(double*)frA * *(double*)frC;
3991 }
3992 /* compute the subtract */
3993 if (is_invalid_operation(processor, cia,
3994 product, *frB,
3995 fpscr_vxsnan | fpscr_vxisi,
3996 0, /*single?*/
3997 0) /*negate?*/) {
3998 invalid_arithemetic_operation(processor, cia,
3999 frT, product, *frB, 0,
4000 0, /*instruction_is_frsp*/
4001 0, /*instruction_is_convert_to_64bit*/
4002 0, /*instruction_is_convert_to_32bit*/
4003 0); /*single-precision*/
4004 }
4005 else {
4006 /*HACK!*/
4007 double s = product - *(double*)frB;
4008 *(double*)frT = s;
4009 }
4010 FPSCR_END(Rc);
4011 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4012
40130.59,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract Single
4014*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4015*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4016*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4017*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4018 FPSCR_BEGIN;
4019 float product; /*HACK! - incorrectly loosing precision ... */
4020 /* compute the multiply */
4021 if (is_invalid_operation(processor, cia,
4022 *frA, *frC,
4023 fpscr_vxsnan | fpscr_vximz,
4024 1, /*single?*/
4025 0) /*negate?*/) {
4026 invalid_arithemetic_operation(processor, cia,
4027 (unsigned64*)&product, *frA, 0, *frC,
4028 0, /*instruction_is_frsp*/
4029 0, /*instruction_is_convert_to_64bit*/
4030 0, /*instruction_is_convert_to_32bit*/
4031 0); /*single-precision*/
4032 }
4033 else {
4034 /*HACK!*/
4035 product = *(double*)frA * *(double*)frC;
4036 }
4037 /* compute the subtract */
4038 if (is_invalid_operation(processor, cia,
4039 product, *frB,
4040 fpscr_vxsnan | fpscr_vxisi,
4041 1, /*single?*/
4042 0) /*negate?*/) {
4043 invalid_arithemetic_operation(processor, cia,
4044 frT, product, *frB, 0,
4045 0, /*instruction_is_frsp*/
4046 0, /*instruction_is_convert_to_64bit*/
4047 0, /*instruction_is_convert_to_32bit*/
4048 0); /*single-precision*/
4049 }
4050 else {
4051 /*HACK!*/
4052 float s = product - *(double*)frB;
4053 *(double*)frT = (double)s;
4054 }
4055 FPSCR_END(Rc);
4056 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4057
40580.63,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add
4059*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
4060*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
4061*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
4062*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4063 FPSCR_BEGIN;
4064 double product; /*HACK! - incorrectly loosing precision ... */
4065 /* compute the multiply */
4066 if (is_invalid_operation(processor, cia,
4067 *frA, *frC,
4068 fpscr_vxsnan | fpscr_vximz,
4069 0, /*single?*/
4070 0) /*negate?*/) {
4071 invalid_arithemetic_operation(processor, cia,
4072 (unsigned64*)&product, *frA, 0, *frC,
4073 0, /*instruction_is_frsp*/
4074 0, /*instruction_is_convert_to_64bit*/
4075 0, /*instruction_is_convert_to_32bit*/
4076 0); /*single-precision*/
4077 }
4078 else {
4079 /*HACK!*/
4080 product = *(double*)frA * *(double*)frC;
4081 }
4082 /* compute the add */
4083 if (is_invalid_operation(processor, cia,
4084 product, *frB,
4085 fpscr_vxsnan | fpscr_vxisi,
4086 0, /*single?*/
4087 0) /*negate?*/) {
4088 invalid_arithemetic_operation(processor, cia,
4089 frT, product, *frB, 0,
4090 0, /*instruction_is_frsp*/
4091 0, /*instruction_is_convert_to_64bit*/
4092 0, /*instruction_is_convert_to_32bit*/
4093 0); /*single-precision*/
4094 }
4095 else {
4096 /*HACK!*/
4097 double s = -(product + *(double*)frB);
4098 *(double*)frT = s;
4099 }
4100 FPSCR_END(Rc);
4101 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4102
41030.59,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add Single
4104*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4105*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4106*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4107*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4108 FPSCR_BEGIN;
4109 float product; /*HACK! - incorrectly loosing precision ... */
4110 /* compute the multiply */
4111 if (is_invalid_operation(processor, cia,
4112 *frA, *frC,
4113 fpscr_vxsnan | fpscr_vximz,
4114 1, /*single?*/
4115 0) /*negate?*/) {
4116 invalid_arithemetic_operation(processor, cia,
4117 (unsigned64*)&product, *frA, 0, *frC,
4118 0, /*instruction_is_frsp*/
4119 0, /*instruction_is_convert_to_64bit*/
4120 0, /*instruction_is_convert_to_32bit*/
4121 0); /*single-precision*/
4122 }
4123 else {
4124 /*HACK!*/
4125 product = *(double*)frA * *(double*)frC;
4126 }
4127 /* compute the add */
4128 if (is_invalid_operation(processor, cia,
4129 product, *frB,
4130 fpscr_vxsnan | fpscr_vxisi,
4131 1, /*single?*/
4132 0) /*negate?*/) {
4133 invalid_arithemetic_operation(processor, cia,
4134 frT, product, *frB, 0,
4135 0, /*instruction_is_frsp*/
4136 0, /*instruction_is_convert_to_64bit*/
4137 0, /*instruction_is_convert_to_32bit*/
4138 0); /*single-precision*/
4139 }
4140 else {
4141 /*HACK!*/
4142 float s = -(product + *(double*)frB);
4143 *(double*)frT = (double)s;
4144 }
4145 FPSCR_END(Rc);
4146 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4147
41480.63,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract
4149*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
4150*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
4151*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
4152*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4153 FPSCR_BEGIN;
4154 double product; /*HACK! - incorrectly loosing precision ... */
4155 /* compute the multiply */
4156 if (is_invalid_operation(processor, cia,
4157 *frA, *frC,
4158 fpscr_vxsnan | fpscr_vximz,
4159 0, /*single?*/
4160 0) /*negate?*/) {
4161 invalid_arithemetic_operation(processor, cia,
4162 (unsigned64*)&product, *frA, 0, *frC,
4163 0, /*instruction_is_frsp*/
4164 0, /*instruction_is_convert_to_64bit*/
4165 0, /*instruction_is_convert_to_32bit*/
4166 0); /*single-precision*/
4167 }
4168 else {
4169 /*HACK!*/
4170 product = *(double*)frA * *(double*)frC;
4171 }
4172 /* compute the subtract */
4173 if (is_invalid_operation(processor, cia,
4174 product, *frB,
4175 fpscr_vxsnan | fpscr_vxisi,
4176 0, /*single?*/
4177 0) /*negate?*/) {
4178 invalid_arithemetic_operation(processor, cia,
4179 frT, product, *frB, 0,
4180 0, /*instruction_is_frsp*/
4181 0, /*instruction_is_convert_to_64bit*/
4182 0, /*instruction_is_convert_to_32bit*/
4183 0); /*single-precision*/
4184 }
4185 else {
4186 /*HACK!*/
4187 double s = -(product - *(double*)frB);
4188 *(double*)frT = s;
4189 }
4190 FPSCR_END(Rc);
4191 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4192
41930.59,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract Single
4194*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4195*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4196*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4197*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4198 FPSCR_BEGIN;
4199 float product; /*HACK! - incorrectly loosing precision ... */
4200 /* compute the multiply */
4201 if (is_invalid_operation(processor, cia,
4202 *frA, *frC,
4203 fpscr_vxsnan | fpscr_vximz,
4204 1, /*single?*/
4205 0) /*negate?*/) {
4206 invalid_arithemetic_operation(processor, cia,
4207 (unsigned64*)&product, *frA, 0, *frC,
4208 0, /*instruction_is_frsp*/
4209 0, /*instruction_is_convert_to_64bit*/
4210 0, /*instruction_is_convert_to_32bit*/
4211 0); /*single-precision*/
4212 }
4213 else {
4214 /*HACK!*/
4215 product = *(double*)frA * *(double*)frC;
4216 }
4217 /* compute the subtract */
4218 if (is_invalid_operation(processor, cia,
4219 product, *frB,
4220 fpscr_vxsnan | fpscr_vxisi,
4221 1, /*single?*/
4222 0) /*negate?*/) {
4223 invalid_arithemetic_operation(processor, cia,
4224 frT, product, *frB, 0,
4225 0, /*instruction_is_frsp*/
4226 0, /*instruction_is_convert_to_64bit*/
4227 0, /*instruction_is_convert_to_32bit*/
4228 0); /*single-precision*/
4229 }
4230 else {
4231 /*HACK!*/
4232 float s = -(product - *(double*)frB);
4233 *(double*)frT = (double)s;
4234 }
4235 FPSCR_END(Rc);
4236 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4237
4238
4239#
4240# I.4.6.6 Floating-Point Rounding and Conversion Instructions
4241#
4242
42430.63,6.FRT,11./,16.FRB,21.12,31.Rc:X:f::Floating Round to Single-Precision
4244*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4245*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4246*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4247*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4248 int sign;
4249 int exp;
4250 unsigned64 frac_grx;
4251 /***/
4252 /* split off cases for what to do */
4253 if (EXTRACTED64(*frB, 1, 11) < 897
4254 && EXTRACTED64(*frB, 1, 63) > 0) {
4255 if ((FPSCR & fpscr_ue) == 0) GOTO(Disabled_Exponent_Underflow);
4256 if ((FPSCR & fpscr_ue) != 0) GOTO(Enabled_Exponent_Underflow);
4257 }
4258 if (EXTRACTED64(*frB, 1, 11) > 1150
4259 && EXTRACTED64(*frB, 1, 11) < 2047) {
4260 if ((FPSCR & fpscr_oe) == 0) GOTO(Disabled_Exponent_Overflow);
4261 if ((FPSCR & fpscr_oe) != 0) GOTO(Enabled_Exponent_Overflow);
4262 }
4263 if (EXTRACTED64(*frB, 1, 11) > 896
4264 && EXTRACTED64(*frB, 1, 11) < 1151) GOTO(Normal_Operand);
4265 if (EXTRACTED64(*frB, 1, 63) == 0) GOTO(Zero_Operand);
4266 if (EXTRACTED64(*frB, 1, 11) == 2047) {
4267 if (EXTRACTED64(*frB, 12, 63) == 0) GOTO(Infinity_Operand);
4268 if (EXTRACTED64(*frB, 12, 12) == 1) GOTO(QNaN_Operand);
4269 if (EXTRACTED64(*frB, 12, 12) == 0
4270 && EXTRACTED64(*frB, 13, 63) > 0) GOTO(SNaN_Operand);
4271 }
4272 /**/
4273 LABEL(Disabled_Exponent_Underflow):
4274 sign = EXTRACTED64(*frB, 0, 0);
4275 if (EXTRACTED64(*frB, 1, 11) == 0) {
4276 exp = -1022;
4277 frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4278 }
4279 if (EXTRACTED64(*frB, 1, 11) > 0) {
4280 exp = EXTRACTED64(*frB, 1, 11) - 1023;
4281 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4282 }
4283 /* G|R|X == zero from above */
4284 while (exp < -126) {
4285 exp = exp - 1;
4286 frac_grx = (INSERTED64(EXTRACTED64(frac_grx, 0, 54), 1, 55)
4287 | MASKED64(frac_grx, 55, 55));
4288 }
4289 FPSCR_SET_UX(EXTRACTED64(frac_grx, 24, 55) > 0);
4290 Round_Single(processor, sign, &exp, &frac_grx);
4291 FPSCR_SET_XX(FPSCR & fpscr_fi);
4292 if (EXTRACTED64(frac_grx, 0, 52) == 0) {
4293 *frT = INSERTED64(sign, 0, 0);
4294 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
4295 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
4296 }
4297 if (EXTRACTED64(frac_grx, 0, 52) > 0) {
4298 if (EXTRACTED64(frac_grx, 0, 0) == 1) {
4299 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4300 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4301 }
4302 if (EXTRACTED64(frac_grx, 0, 0) == 0) {
4303 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_denormalized_number);
4304 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_denormalized_number);
4305 }
4306 /*Normalize_Operand:*/
4307 while (EXTRACTED64(frac_grx, 0, 0) == 0) {
4308 exp = exp - 1;
4309 frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1, 52), 0, 51);
4310 }
4311 *frT = (INSERTED64(sign, 0, 0)
4312 | INSERTED64(exp + 1023, 1, 11)
4313 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4314 }
4315 GOTO(Done);
4316 /**/
4317 LABEL(Enabled_Exponent_Underflow):
4318 FPSCR_SET_UX(1);
4319 sign = EXTRACTED64(*frB, 0, 0);
4320 if (EXTRACTED64(*frB, 1, 11) == 0) {
4321 exp = -1022;
4322 frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4323 }
4324 if (EXTRACTED64(*frB, 1, 11) > 0) {
4325 exp = EXTRACTED64(*frB, 1, 11) - 1023;
4326 frac_grx = (BIT64(0) |
4327 INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52));
4328 }
4329 /*Normalize_Operand:*/
4330 while (EXTRACTED64(frac_grx, 0, 0) == 0) {
4331 exp = exp - 1;
4332 frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1, 52), 0, 51);
4333 }
4334 Round_Single(processor, sign, &exp, &frac_grx);
4335 FPSCR_SET_XX(FPSCR & fpscr_fi);
4336 exp = exp + 192;
4337 *frT = (INSERTED64(sign, 0, 0)
4338 | INSERTED64(exp + 1023, 1, 11)
4339 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4340 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4341 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4342 GOTO(Done);
4343 /**/
4344 LABEL(Disabled_Exponent_Overflow):
4345 FPSCR_SET_OX(1);
4346 if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
4347 if (EXTRACTED64(*frB, 0, 0) == 0) {
4348 *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
4349 FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
4350 }
4351 if (EXTRACTED64(*frB, 0, 0) == 1) {
4352 *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
4353 FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
4354 }
4355 }
4356 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_zero) {
4357 if (EXTRACTED64(*frB, 0, 0) == 0) {
4358 *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
4359 FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4360 }
4361 if (EXTRACTED64(*frB, 0, 0) == 1) {
4362 *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
4363 FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4364 }
4365 }
4366 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_pos_infinity) {
4367 if (EXTRACTED64(*frB, 0, 0) == 0) {
4368 *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
4369 FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
4370 }
4371 if (EXTRACTED64(*frB, 0, 0) == 1) {
4372 *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
4373 FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4374 }
4375 }
4376 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_neg_infinity) {
4377 if (EXTRACTED64(*frB, 0, 0) == 0) {
4378 *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
4379 FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4380 }
4381 if (EXTRACTED64(*frB, 0, 0) == 1) {
4382 *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
4383 FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
4384 }
4385 }
4386 /* FPSCR[FR] <- undefined */
4387 FPSCR_SET_FI(1);
4388 FPSCR_SET_XX(1);
4389 GOTO(Done);
4390 /**/
4391 LABEL(Enabled_Exponent_Overflow):
4392 sign = EXTRACTED64(*frB, 0, 0);
4393 exp = EXTRACTED64(*frB, 1, 11) - 1023;
4394 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4395 Round_Single(processor, sign, &exp, &frac_grx);
4396 FPSCR_SET_XX(FPSCR & fpscr_fi);
4397 /**/
4398 LABEL(Enabled_Overflow):
4399 FPSCR_SET_OX(1);
4400 exp = exp - 192;
4401 *frT = (INSERTED64(sign, 0, 0)
4402 | INSERTED64(exp + 1023, 1, 11)
4403 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4404 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4405 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4406 GOTO(Done);
4407 /**/
4408 LABEL(Zero_Operand):
4409 *frT = *frB;
4410 if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
4411 if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
4412 FPSCR_SET_FR(0);
4413 FPSCR_SET_FI(0);
4414 GOTO(Done);
4415 /**/
4416 LABEL(Infinity_Operand):
4417 *frT = *frB;
4418 if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
4419 if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
4420 FPSCR_SET_FR(0);
4421 FPSCR_SET_FI(0);
4422 GOTO(Done);
4423 /**/
4424 LABEL(QNaN_Operand):
4425 *frT = INSERTED64(EXTRACTED64(*frB, 0, 34), 0, 34);
4426 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
4427 FPSCR_SET_FR(0);
4428 FPSCR_SET_FI(0);
4429 GOTO(Done);
4430 /**/
4431 LABEL(SNaN_Operand):
4432 FPSCR_OR_VX(fpscr_vxsnan);
4433 if ((FPSCR & fpscr_ve) == 0) {
4434 *frT = (MASKED64(*frB, 0, 11)
4435 | BIT64(12)
4436 | MASKED64(*frB, 13, 34));
4437 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
4438 }
4439 FPSCR_SET_FR(0);
4440 FPSCR_SET_FI(0);
4441 GOTO(Done);
4442 /**/
4443 LABEL(Normal_Operand):
4444 sign = EXTRACTED64(*frB, 0, 0);
4445 exp = EXTRACTED64(*frB, 1, 11) - 1023;
4446 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
4447 Round_Single(processor, sign, &exp, &frac_grx);
4448 FPSCR_SET_XX(FPSCR & fpscr_fi);
4449 if (exp > 127 && (FPSCR & fpscr_oe) == 0) GOTO(Disabled_Exponent_Overflow);
4450 if (exp > 127 && (FPSCR & fpscr_oe) != 0) GOTO(Enabled_Overflow);
4451 *frT = (INSERTED64(sign, 0, 0)
4452 | INSERTED64(exp + 1023, 1, 11)
4453 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
4454 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4455 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
4456 GOTO(Done);
4457 /**/
4458 LABEL(Done):
4459 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
4460
4461
44620.63,6.FRT,11./,16.FRB,21.814,31.Rc:X:64,f::Floating Convert To Integer Doubleword
4463 floating_point_assist_interrupt(processor, cia);
4464
44650.63,6.FRT,11./,16.FRB,21.815,31.Rc:X:64,f::Floating Convert To Integer Doubleword with round towards Zero
4466 floating_point_assist_interrupt(processor, cia);
4467
44680.63,6.FRT,11./,16.FRB,21.14,31.Rc:X:f::Floating Convert To Integer Word
4469 floating_point_assist_interrupt(processor, cia);
4470
44710.63,6.FRT,11./,16.FRB,21.15,31.Rc:X:f:fctiwz:Floating Convert To Integer Word with round towards Zero
4472*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4473*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4474*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4475*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4476 FPSCR_BEGIN;
4477 convert_to_integer(processor, cia,
4478 frT, *frB,
4479 fpscr_rn_round_towards_zero, 32);
4480 FPSCR_END(Rc);
4481 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
4482
44830.63,6.FRT,11./,16.FRB,21.846,31.Rc:X:64,f::Floating Convert from Integer Doubleword
4484 int sign = EXTRACTED64(*frB, 0, 0);
4485 int exp = 63;
4486 unsigned64 frac = *frB;
4487 /***/
4488 if (frac == 0) GOTO(Zero_Operand);
4489 if (sign == 1) frac = ~frac + 1;
4490 while (EXTRACTED64(frac, 0, 0) == 0) {
4491 /*??? do the loop 0 times if (FRB) = max negative integer */
4492 frac = INSERTED64(EXTRACTED64(frac, 1, 63), 0, 62);
4493 exp = exp - 1;
4494 }
4495 Round_Float(processor, sign, &exp, &frac, FPSCR & fpscr_rn);
4496 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4497 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
4498 *frT = (INSERTED64(sign, 0, 0)
4499 | INSERTED64(exp + 1023, 1, 11)
4500 | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
4501 GOTO(Done);
4502 /**/
4503 LABEL(Zero_Operand):
4504 FPSCR_SET_FR(0);
4505 FPSCR_SET_FI(0);
4506 FPSCR_SET_FPRF(fpscr_rf_pos_zero);
4507 *frT = 0;
4508 GOTO(Done);
4509 /**/
4510 LABEL(Done):
4511 PPC_INSN_FLOAT(FRT_BITMASK, FRB_BITMASK, Rc);
4512
4513
4514#
4515# I.4.6.7 Floating-Point Compare Instructions
4516#
4517
45180.63,6.BF,9./,11.FRA,16.FRB,21.0,31./:X:f:fcmpu:Floating Compare Unordered
4519*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4520*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4521*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4522*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4523 FPSCR_BEGIN;
4524 unsigned c;
4525 if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
4526 c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
4527 else if (is_less_than(frA, frB))
4528 c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
4529 else if (is_greater_than(frA, frB))
4530 c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
4531 else
4532 c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
4533 FPSCR_SET_FPCC(c);
4534 CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
4535 if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0))
4536 FPSCR_OR_VX(fpscr_vxsnan);
4537 FPSCR_END(0);
4538 PPC_INSN_FLOAT_CR(0, FRA_BITMASK | FRB_BITMASK, BF_BITMASK);
4539
45400.63,6.BF,9./,11.FRA,16.FRB,21.32,31./:X:f:fcmpo:Floating Compare Ordered
4541*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
4542*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4543*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4544*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4545 FPSCR_BEGIN;
4546 unsigned c;
4547 if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
4548 c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
4549 else if (is_less_than(frA, frB))
4550 c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
4551 else if (is_greater_than(frA, frB))
4552 c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
4553 else
4554 c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
4555 FPSCR_SET_FPCC(c);
4556 CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
4557 if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0)) {
4558 FPSCR_OR_VX(fpscr_vxsnan);
4559 if ((FPSCR & fpscr_ve) == 0)
4560 FPSCR_OR_VX(fpscr_vxvc);
4561 }
4562 else if (is_QNaN(*frA, 0) || is_QNaN(*frB, 0)) {
4563 FPSCR_OR_VX(fpscr_vxvc);
4564 }
4565 FPSCR_END(0);
4566 PPC_INSN_FLOAT_CR(0, FRA_BITMASK | FRB_BITMASK, BF_BITMASK);
4567
4568
4569#
4570# I.4.6.8 Floating-Point Status and Control Register Instructions
4571#
4572
45730.63,6.FRT,11./,16./,21.583,31.Rc:X:f::Move From FPSCR
4574 FPSCR_BEGIN;
4575 *frT = FPSCR;
4576 FPSCR_END(Rc);
4577
45780.63,6.BF,9./,11.BFA,14./,16./,21.64,31./:X:f::Move to Condition Register from FPSCR
4579 FPSCR_BEGIN;
4580 unsigned field = FPSCR_FIELD(BFA);
4581 CR_SET(BF, field);
4582 FPSCR_SET(BFA, 0); /* FPSCR_END fixes up FEX/VX */
4583 FPSCR_END(0);
4584
45850.64,6.BF,9./,11./,16.U,20./,21.134,31.Rc:X:f::Move To FPSCR Field Immediate
4586 FPSCR_BEGIN;
4587 FPSCR_SET(BF, U);
4588 FPSCR_END(Rc);
4589
45900.63,6./,7.FLM,15./,16.FRB,21.711,31.Rc:XFL:f::Move To FPSCR Fields
4591 FPSCR_BEGIN;
4592 int i;
4593 for (i = 0; i < 8; i++) {
4594 if ((FLM & BIT8(i))) {
4595 FPSCR &= ~MASK32(i*4, i*4+3);
4596 FPSCR |= MASKED32(*frB, i*4, i*4+3);
4597 }
4598 }
4599 FPSCR_END(Rc);
4600
46010.63,6.BT,11./,16./,21.70,31.Rc:X:f::Move To FPSCR Bit 0
4602 FPSCR_BEGIN;
4603 unsigned32 bit = BIT32(BT);
4604 FPSCR &= ~bit;
4605 FPSCR_END(Rc);
4606
46070.63,6.BT,11./,16./,21.38,31.Rc:X:f::Move To FPSCR Bit 1
4608 FPSCR_BEGIN;
4609 unsigned32 bit = BIT32(BT);
4610 if (bit & fpscr_fi)
4611 bit |= fpscr_xx;
4612 if ((bit & fpscr_vx_bits))
4613 bit |= fpscr_fx;
4614 /* note - omit vx bit */
4615 if ((bit & (fpscr_ox | fpscr_ux | fpscr_zx | fpscr_xx)))
4616 bit |= fpscr_fx;
4617 FPSCR |= bit;
4618 FPSCR_END(Rc);
4619
4620
4621#
4622# I.A.1.1 Floating-Point Store Instruction
4623#
46240.31,6.FRS,11.RA,16.RB,21.983,31./:X:f,o::Store Floating-Point as Integer Word Indexed
4625 program_interrupt(processor, cia, optional_instruction_program_interrupt);
4626
4627#
4628# I.A.1.2 Floating-Point Arithmetic Instructions
4629#
4630
46310.63,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f,o::Floating Square Root
4632 program_interrupt(processor, cia, optional_instruction_program_interrupt);
4633
46340.59,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f,o::Floating Square Root Single
4635 program_interrupt(processor, cia, optional_instruction_program_interrupt);
4636
46370.59,6.FRT,11./,16.FRB,21./,26.24,31.Rc:A:f,o::Floating Reciprocal Estimate Single
4638 program_interrupt(processor, cia, optional_instruction_program_interrupt);
4639
46400.63,6.FRT,11./,16.FRB,21./,26.26,31.Rc:A:f,o::Floating Reciprocal Square Root Estimate
4641 program_interrupt(processor, cia, optional_instruction_program_interrupt);
4642
4643#
4644# I.A.1.3 Floating-Point Select Instruction
4645#
4646
46470.63,6.FRT,11.FRA,16.FRB,21.FRC,26.23,31.Rc:A:f,o::Floating Select
4648*601: PPC_UNIT_BAD, PPC_UNIT_BAD, 0, 0, 0
4649*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4650*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4651*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
4652 if (CURRENT_MODEL == MODEL_ppc601) {
4653 program_interrupt(processor, cia, optional_instruction_program_interrupt);
4654 } else {
4655 unsigned64 zero = 0;
4656 FPSCR_BEGIN;
4657 if (is_NaN(*frA, 0) || is_less_than (frA, &zero)) *frT = *frB;
4658 else *frT = *frC;
4659 FPSCR_END(Rc);
4660 PPC_INSN_FLOAT(FRT_BITMASK, FRA_BITMASK | FRB_BITMASK | FRC_BITMASK, Rc);
4661 }
4662
4663#
4664# II.3.2 Cache Management Instructions
4665#
4666
46670.31,6./,11.RA,16.RB,21.982,31./:X::icbi:Instruction Cache Block Invalidate
4668*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4669*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4670*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4671*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
4672 /* blindly flush all instruction cache entries */
4673 #if WITH_IDECODE_CACHE_SIZE
4674 cpu_flush_icache(processor);
4675 #endif
4676 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0);
4677
46780.19,6./,11./,16./,21.150,31./:XL::isync:Instruction Synchronize
4679*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4680*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4681*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4682*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
4683 cpu_synchronize_context(processor, cia);
4684 PPC_INSN_INT(0, 0, 0);
4685
4686
4687#
4688# II.3.2.2 Data Cache Instructions
4689#
4690
46910.31,6./,11.RA,16.RB,21.278,31./:X:::Data Cache Block Touch
4692*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4693*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4694*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4695*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
4696 TRACE(trace_tbd,("Data Cache Block Touch\n"));
4697 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4698
46990.31,6./,11.RA,16.RB,21.246,31./:X:::Data Cache Block Touch for Store
4700*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4701*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4702*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4703*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4704 TRACE(trace_tbd,("Data Cache Block Touch for Store\n"));
4705 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4706
47070.31,6./,11.RA,16.RB,21.1014,31./:X:::Data Cache Block set to Zero
4708*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4709*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 10, 10, 0
4710*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 10, 10, 0
4711*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4712 TRACE(trace_tbd,("Data Cache Block set to Zero\n"));
4713 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4714
47150.31,6./,11.RA,16.RB,21.54,31./:X:::Data Cache Block Store
4716*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4717*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
4718*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
4719*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
4720 TRACE(trace_tbd,("Data Cache Block Store\n"));
4721 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4722
47230.31,6./,11.RA,16.RB,21.86,31./:X:::Data Cache Block Flush
4724*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4725*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
4726*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
4727*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
4728 TRACE(trace_tbd,("Data Cache Block Flush\n"));
4729 PPC_INSN_INT(0, (RA_BITMASK & ~1) | RB_BITMASK, 0/*Rc*/);
4730
4731#
4732# II.3.3 Enforce In-order Execution of I/O Instruction
4733#
4734
47350.31,6./,11./,16./,21.854,31./:X::eieio:Enforce In-order Execution of I/O
4736 /* Since this model has no instruction overlap
4737 this instruction need do nothing */
4738
4739#
4740# II.4.1 Time Base Instructions
4741#
4742
47430.31,6.RT,11.tbr,21.371,31./:XFX::mftb:Move From Time Base
4744*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
4745*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
4746*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
4747 int n = (tbr{5:9} << 5) | tbr{0:4};
4748 if (n == 268) {
4749 if (is_64bit_implementation) *rT = TB;
4750 else *rT = EXTRACTED64(TB, 32, 63);
4751 }
4752 else if (n == 269) {
4753 if (is_64bit_implementation) *rT = EXTRACTED64(TB, 0, 31);
4754 else *rT = EXTRACTED64(TB, 0, 31);
4755 }
4756 else
4757 program_interrupt(processor, cia,
4758 illegal_instruction_program_interrupt);
4759
4760
4761#
4762# III.2.3.1 System Linkage Instructions
4763#
4764
47650.19,6./,11./,16./,21.50,31./:XL::rfi:Return From Interrupt
4766*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4767*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4768*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4769*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
4770 if (IS_PROBLEM_STATE(processor)) {
4771 program_interrupt(processor, cia,
4772 privileged_instruction_program_interrupt);
4773 }
4774 else {
4775 MSR = (MASKED(SRR1, 0, 32)
4776 | MASKED(SRR1, 37, 41)
4777 | MASKED(SRR1, 48, 63));
4778 NIA = MASKED(SRR0, 0, 61);
4779 cpu_synchronize_context(processor, cia);
4780 check_masked_interrupts(processor);
4781 }
4782
4783#
4784# III.3.4.1 Move to/from System Register Instructions
4785#
4786
4787#0.31,6.RS,11.SPR,21.467,31./:XFX:::Move To Special Purpose Register
4788#0.31,6.RT,11.SPR,21.339,31./:XFX:::Move From Special Purpose Register
47890.31,6.RS,11./,16./,21.146,31./:X:::Move To Machine State Register
4790*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4791*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4792*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4793*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4794 if (IS_PROBLEM_STATE(processor))
4795 program_interrupt(processor, cia,
4796 privileged_instruction_program_interrupt);
4797 else {
4798 MSR = *rS;
4799 check_masked_interrupts(processor);
4800 }
4801
48020.31,6.RT,11./,16./,21.83,31./:X:::Move From Machine State Register
4803*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4804*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
4805*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
4806*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
4807 if (IS_PROBLEM_STATE(processor))
4808 program_interrupt(processor, cia,
4809 privileged_instruction_program_interrupt);
4810 else {
4811 *rT = MSR;
4812 check_masked_interrupts(processor);
4813 }
4814
4815
4816#
4817# III.4.11.1 Cache Management Instructions
4818#
4819
48200.31,6./,11.RA,16.RB,21.470,31./:X::dcbi:Data Cache Block Invalidate
4821*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4822*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4823*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
4824*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
4825 if (IS_PROBLEM_STATE(processor))
4826 program_interrupt(processor, cia,
4827 privileged_instruction_program_interrupt);
4828 else
4829 TRACE(trace_tbd,("Data Cache Block Invalidate\n"));
4830
4831#
4832# III.4.11.2 Segment Register Manipulation Instructions
4833#
4834
48350.31,6.RS,11./,12.SR,16./,21.210,31./:X:32:mtsr %SR,%RS:Move To Segment Register
4836*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4837*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4838*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4839*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4840 if (IS_PROBLEM_STATE(processor))
4841 program_interrupt(processor, cia,
4842 privileged_instruction_program_interrupt);
4843 else
4844 SEGREG(SR) = *rS;
4845
48460.31,6.RS,11./,16.RB,21.242,31./:X:32:mtsrin %RS,%RB:Move To Segment Register Indirect
4847*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
4848*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4849*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
4850*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4851 if (IS_PROBLEM_STATE(processor))
4852 program_interrupt(processor, cia,
4853 privileged_instruction_program_interrupt);
4854 else
4855 SEGREG(EXTRACTED32(*rB, 0, 3)) = *rS;
4856
48570.31,6.RT,11./,12.SR,16./,21.595,31./:X:32:mfsr %RT,%RS:Move From Segment Register
4858*601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
4859*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4860*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4861*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4862 if (IS_PROBLEM_STATE(processor))
4863 program_interrupt(processor, cia,
4864 privileged_instruction_program_interrupt);
4865 else
4866 *rT = SEGREG(SR);
4867
48680.31,6.RT,11./,16.RB,21.659,31./:X:32:mfsrin %RT,%RB:Move From Segment Register Indirect
4869*601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
4870*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4871*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
4872*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
4873 if (IS_PROBLEM_STATE(processor))
4874 program_interrupt(processor, cia,
4875 privileged_instruction_program_interrupt);
4876 else
4877 *rT = SEGREG(EXTRACTED32(*rB, 0, 3));
4878
4879
4880#
4881# III.4.11.3 Lookaside Buffer Management Instructions (Optional)
4882#
4883
48840.31,6./,11./,16.RB,21.434,31./:X:64::SLB Invalidate Entry
4885
48860.31,6./,11./,16./,21.498,31./:X:64::SLB Invalidate All
4887
48880.31,6./,11./,16.RB,21.306,31./:X:::TLB Invalidate Entry
4889 if (IS_PROBLEM_STATE(processor))
4890 program_interrupt(processor, cia,
4891 privileged_instruction_program_interrupt);
4892 else {
4893 int nr = 0;
4894 cpu *proc;
4895 while (1) {
4896 proc = psim_cpu(cpu_system(processor), nr);
4897 if (proc == NULL) break;
4898 cpu_page_tlb_invalidate_entry(proc, *rB);
4899 nr++;
4900 }
4901 }
4902
49030.31,6./,11./,16./,21.370,31./:X:::TLB Invalidate All
4904 if (IS_PROBLEM_STATE(processor))
4905 program_interrupt(processor, cia,
4906 privileged_instruction_program_interrupt);
4907 else {
4908 int nr = 0;
4909 cpu *proc;
4910 while (1) {
4911 proc = psim_cpu(cpu_system(processor), nr);
4912 if (proc == NULL) break;
4913 cpu_page_tlb_invalidate_all(proc);
4914 nr++;
4915 }
4916 }
4917
49180.31,6./,11./,16./,21.566,31./:X:::TLB Synchronize
4919 /* nothing happens here - always in sync */
4920
4921#
4922# III.A.1.2 External Access Instructions
4923#
4924
49250.31,6.RT,11.RA,16.RB,21.310,31./:X:earwax::External Control In Word Indexed
4926
49270.31,6.RS,11.RA,16.RB,21.438,31./:X:earwax::External Control Out Word Indexed
This page took 0.232568 seconds and 4 git commands to generate.