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