More model specific changes
[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_FUNCTION_UNIT_UNKNOWN, PPC_FUNCTION_UNIT_UNKNOWN, 1, 1, 0
70 ::model:603e:ppc603e:PPC_FUNCTION_UNIT_UNKNOWN, PPC_FUNCTION_UNIT_UNKNOWN, 1, 1, 0
71 ::model:603:ppc603:PPC_FUNCTION_UNIT_UNKNOWN, PPC_FUNCTION_UNIT_UNKNOWN, 1, 1, 0
72
73 # Flags for model.h
74 ::model-data:::
75 typedef enum _ppc_function_unit {
76 PPC_FUNCTION_UNIT_UNKNOWN, /* unknown function unit */
77 PPC_FUNCTION_UNIT_IU, /* integer unit (603 style) */
78 PPC_FUNCTION_UNIT_SRU, /* system register unit (603 style) */
79 PPC_FUNCTION_UNIT_SCIU1, /* 1st single cycle integer unit (604 style) */
80 PPC_FUNCTION_UNIT_SCIU2, /* 2nd single cycle integer unit (604 style) */
81 PPC_FUNCTION_UNIT_MCIU, /* multiple cycle integer unit (604 style) */
82 PPC_FUNCTION_UNIT_FPU, /* floating point unit */
83 PPC_FUNCTION_UNIT_LSU, /* load/store unit */
84 PPC_FUNCTION_UNIT_BPU, /* branch unit */
85 nr_ppc_function_units
86 } ppc_function_unit;
87
88 /* Structure to hold timing information on a per instruction basis */
89 struct _model_time {
90 ppc_function_unit first_unit; /* first functional unit this insn could use */
91 ppc_function_unit last_unit; /* last functional unit this insn could use */
92 unsigned16 issue; /* # cycles before function unit can process other insns */
93 unsigned16 done; /* # cycles before insn is done */
94 unsigned32 flags; /* flag bits */
95 };
96
97 /* Flags */
98 #define PPC_LOAD 0x00000001 /* insn is a load */
99 #define PPC_STORE 0x00000002 /* insn is a store */
100 #define PPC_SERIALIZE 0x00000004 /* insn forces serialization */
101
102 /* Structure to hold the current state information for the simulated CPU model */
103 struct _model_data {
104 const char *name; /* model name */
105 const model_time *timing; /* timing information */
106 unsigned_word old_program_counter; /* previous PC */
107 unsigned nr_branches; /* # branches */
108 unsigned nr_units[nr_ppc_function_units]; /* function unit counts */
109 unsigned16 busy[nr_ppc_function_units]; /* how long until free */
110 };
111
112 STATIC_MODEL const char *const ppc_function_unit_name[ (int)nr_ppc_function_units ] = {
113 "unknown functional unit",
114 "integer functional unit",
115 "system register functional unit",
116 "1st single cycle integer functional unit",
117 "2nd single cycle integer functional unit",
118 "multiple cycle integer functional unit",
119 "floating point functional unit",
120 "load/store functional unit",
121 "branch functional unit",
122 };
123
124 model_data *::model-function::model_create:cpu *processor
125 if (CURRENT_MODEL == MODEL_NONE)
126 return (model_data *)0;
127 else {
128 model_data *model_ptr = ZALLOC(model_data);
129 model_ptr->name = model_name[CURRENT_MODEL];
130 model_ptr->timing = model_time_mapping[CURRENT_MODEL];
131 return model_ptr;
132 }
133
134 void::model-function::model_init:cpu *processor, model_data *model_ptr
135 void::model-function::model_halt:cpu *processor, model_data *model_ptr
136
137 void::model-function::model_issue:itable_index index, model_data *model_ptr, unsigned_word cia
138 if (model_ptr->old_program_counter+4 != cia)
139 model_ptr->nr_branches++;
140
141 model_ptr->old_program_counter = cia;
142 model_ptr->nr_units[ (int)model_ptr->timing[ (int)index ].first_unit ]++;
143
144 model_print *::model-function::model_mon_info:model_data *model_ptr
145 model_print *head;
146 model_print *tail;
147 ppc_function_unit i;
148
149 head = tail = ZALLOC(model_print);
150 tail->count = model_ptr->nr_branches;
151 tail->name = "branch";
152 tail->suffix_plural = "es";
153 tail->suffix_singular = "";
154
155 for (i = PPC_FUNCTION_UNIT_UNKNOWN; i < nr_ppc_function_units; i++) {
156 if (model_ptr->nr_units[i]) {
157 tail->next = ZALLOC(model_print);
158 tail = tail->next;
159 tail->count = model_ptr->nr_units[i];
160 tail->name = ppc_function_unit_name[i];
161 tail->suffix_plural = "s";
162 tail->suffix_singular = "";
163 }
164 }
165
166 tail->next = (model_print *)0;
167 return head;
168
169 void::model-function::model_mon_info_free:model_data *model_ptr, model_print *ptr
170 model_print *next;
171
172 while (ptr) {
173 next = ptr->next;
174 free((void *)ptr);
175 ptr = next;
176 }
177
178
179 # The following (illegal) instruction is `known' by gen and is
180 # called when ever an illegal instruction is encountered
181 ::internal::illegal
182 program_interrupt(processor, cia,
183 illegal_instruction_program_interrupt);
184 return 0;
185
186
187 # The following (floating point unavailable) instruction is `known' by gen
188 # and is called when ever an a floating point instruction is to be
189 # executed but floating point is make unavailable by the MSR
190 ::internal::floating_point_unavailable
191 floating_point_unavailable_interrupt(processor, cia);
192 return 0;
193
194
195 #
196 # Floating point support functions
197 #
198
199 # Convert 32bit single to 64bit double
200 unsigned64::function::DOUBLE:unsigned32 WORD
201 unsigned64 FRT;
202 if (EXTRACTED32(WORD, 1, 8) > 0
203 && EXTRACTED32(WORD, 1, 8) < 255) {
204 /* normalized operand */
205 int not_word_1_1 = !EXTRACTED32(WORD, 1, 1); /*2.6.3 bug*/
206 FRT = (INSERTED64(EXTRACTED32(WORD, 0, 1), 0, 1)
207 | INSERTED64(not_word_1_1, 2, 2)
208 | INSERTED64(not_word_1_1, 3, 3)
209 | INSERTED64(not_word_1_1, 4, 4)
210 | INSERTED64(EXTRACTED32(WORD, 2, 31), 5, (63 - 29)));
211 }
212 else if (EXTRACTED32(WORD, 1, 8) == 0
213 && EXTRACTED32(WORD, 9, 31) != 0) {
214 /* denormalized operand */
215 int sign = EXTRACTED32(WORD, 0, 0);
216 int exp = -126;
217 unsigned64 frac = INSERTED64(EXTRACTED32(WORD, 9, 31), 1, (52 - 29));
218 /* normalize the operand */
219 while (MASKED64(frac, 0, 0) == 0) {
220 frac <<= 1;
221 exp -= 1;
222 }
223 FRT = (INSERTED64(sign, 0, 0)
224 | INSERTED64(exp + 1023, 1, 11)
225 | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
226 }
227 else if (EXTRACTED32(WORD, 1, 8) == 255
228 || EXTRACTED32(WORD, 1, 31) == 0) {
229 FRT = (INSERTED64(EXTRACTED32(WORD, 0, 1), 0, 1)
230 | INSERTED64(EXTRACTED32(WORD, 1, 1), 2, 2)
231 | INSERTED64(EXTRACTED32(WORD, 1, 1), 3, 3)
232 | INSERTED64(EXTRACTED32(WORD, 1, 1), 4, 4)
233 | INSERTED64(EXTRACTED32(WORD, 2, 31), 5, (63 - 29)));
234 }
235 else {
236 error("DOUBLE - unknown case\n");
237 FRT = 0;
238 }
239 return FRT;
240
241 # Convert 64bit single to 32bit double
242 unsigned32::function::SINGLE:unsigned64 FRS
243 unsigned32 WORD;
244 if (EXTRACTED64(FRS, 1, 11) > 896
245 || EXTRACTED64(FRS, 1, 63) == 0) {
246 /* no denormalization required (includes Zero/Infinity/NaN) */
247 WORD = (INSERTED32(EXTRACTED64(FRS, 0, 1), 0, 1)
248 | INSERTED32(EXTRACTED64(FRS, 5, 34), 2, 31));
249 }
250 else if (874 <= EXTRACTED64(FRS, 1, 11)
251 && EXTRACTED64(FRS, 1, 11) <= 896) {
252 /* denormalization required */
253 int sign = EXTRACTED64(FRS, 0, 0);
254 int exp = EXTRACTED64(FRS, 1, 11) - 1023;
255 unsigned64 frac = (BIT64(0)
256 | INSERTED64(EXTRACTED64(FRS, 12, 63), 1, 52));
257 /* denormalize the operand */
258 while (exp < -126) {
259 frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63);
260 exp += 1;
261 }
262 WORD = (INSERTED32(sign, 0, 0)
263 | INSERTED32(0x00, 1, 8)
264 | INSERTED32(EXTRACTED64(frac, 1, 23), 9, 31));
265 }
266 else {
267 WORD = 0x0; /* ??? */
268 }
269 return WORD;
270
271
272 # round 64bit double to 64bit but single
273 void::function::Round_Single:cpu *processor, int sign, int *exp, unsigned64 *frac_grx
274 /* comparisons ignore u bits */
275 unsigned64 out;
276 int inc = 0;
277 int lsb = EXTRACTED64(*frac_grx, 23, 23);
278 int gbit = EXTRACTED64(*frac_grx, 24, 24);
279 int rbit = EXTRACTED64(*frac_grx, 25, 25);
280 int xbit = EXTRACTED64(*frac_grx, 26, 55) != 0;
281 if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
282 if (lsb == 1 && gbit == 1) inc = 1;
283 if (lsb == 0 && gbit == 1 && rbit == 1) inc = 1;
284 if (lsb == 0 && gbit == 1 && xbit == 1) inc = 1;
285 }
286 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_pos_infinity) {
287 if (sign == 0 && gbit == 1) inc = 1;
288 if (sign == 0 && rbit == 1) inc = 1;
289 if (sign == 0 && xbit == 1) inc = 1;
290 }
291 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_neg_infinity) {
292 if (sign == 1 && gbit == 1) inc = 1;
293 if (sign == 1 && rbit == 1) inc = 1;
294 if (sign == 1 && xbit == 1) inc = 1;
295 }
296 /* work out addition in low 25 bits of out */
297 out = EXTRACTED64(*frac_grx, 0, 23) + inc;
298 *frac_grx = INSERTED64(out, 0, 23);
299 if (out & BIT64(64 - 23 - 1 - 1)) {
300 *frac_grx = (BIT64(0) |
301 INSERTED64(EXTRACTED64(*frac_grx, 0, 22), 1, 23));
302 *exp = *exp + 1;
303 }
304 /* frac_grx[24:52] = 0 already */
305 FPSCR_SET_FR(inc);
306 FPSCR_SET_FI(gbit || rbit || xbit);
307
308
309 #
310 void::function::Round_Integer:cpu *processor, int sign, unsigned64 *frac, int *frac64, int gbit, int rbit, int xbit, fpscreg round_mode
311 int inc = 0;
312 if (round_mode == fpscr_rn_round_to_nearest) {
313 if (*frac64 == 1 && gbit == 1) inc = 1;
314 if (*frac64 == 0 && gbit == 1 && rbit == 1) inc = 1;
315 if (*frac64 == 0 && gbit == 1 && xbit == 1) inc = 1;
316 }
317 if (round_mode == fpscr_rn_round_towards_pos_infinity) {
318 if (sign == 0 && gbit == 1) inc = 1;
319 if (sign == 0 && rbit == 1) inc = 1;
320 if (sign == 0 && xbit == 1) inc = 1;
321 }
322 if (round_mode == fpscr_rn_round_towards_neg_infinity) {
323 if (sign == 1 && gbit == 1) inc = 1;
324 if (sign == 1 && rbit == 1) inc = 1;
325 if (sign == 1 && xbit == 1) inc = 1;
326 }
327 /* frac[0:64] = frac[0:64} + inc */
328 *frac += (*frac64 && inc ? 1 : 0);
329 *frac64 = (*frac64 + inc) & 0x1;
330 FPSCR_SET_FR(inc);
331 FPSCR_SET_FI(gbit | rbit | xbit);
332
333
334 void::function::Round_Float:cpu *processor, int sign, int *exp, unsigned64 *frac, fpscreg round_mode
335 int carry_out;
336 int inc = 0;
337 int lsb = EXTRACTED64(*frac, 52, 52);
338 int gbit = EXTRACTED64(*frac, 53, 53);
339 int rbit = EXTRACTED64(*frac, 54, 54);
340 int xbit = EXTRACTED64(*frac, 55, 55);
341 if (round_mode == fpscr_rn_round_to_nearest) {
342 if (lsb == 1 && gbit == 1) inc = 1;
343 if (lsb == 0 && gbit == 1 && rbit == 1) inc = 1;
344 if (lsb == 0 && gbit == 1 && xbit == 1) inc = 1;
345 }
346 if (round_mode == fpscr_rn_round_towards_pos_infinity) {
347 if (sign == 0 && gbit == 1) inc = 1;
348 if (sign == 0 && rbit == 1) inc = 1;
349 if (sign == 0 && xbit == 1) inc = 1;
350 }
351 if (round_mode == fpscr_rn_round_towards_neg_infinity) {
352 if (sign == 1 && gbit == 1) inc = 1;
353 if (sign == 1 && rbit == 1) inc = 1;
354 if (sign == 1 && xbit == 1) inc = 1;
355 }
356 /* frac//carry_out = frac + inc */
357 *frac = (*frac >> 1) + (INSERTED64(inc, 52, 52) >> 1);
358 carry_out = EXTRACTED64(*frac, 0, 0);
359 *frac <<= 1;
360 if (carry_out == 1) *exp = *exp + 1;
361 FPSCR_SET_FR(inc);
362 FPSCR_SET_FI(gbit | rbit | xbit);
363 FPSCR_SET_XX(FPSCR & fpscr_fi);
364
365
366 # conversion of FP to integer
367 void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64 *frt, unsigned64 frb, fpscreg round_mode, int tgt_precision
368 int i;
369 int exp = 0;
370 unsigned64 frac = 0;
371 int frac64 = 0;
372 int gbit = 0;
373 int rbit = 0;
374 int xbit = 0;
375 int sign = EXTRACTED64(frb, 0, 0);
376 if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 63) == 0)
377 goto Infinity_Operand;
378 if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 0)
379 goto SNaN_Operand;
380 if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 1)
381 goto QNaN_Operand;
382 if (EXTRACTED64(frb, 1, 11) > 1086) goto Large_Operand;
383 if (EXTRACTED64(frb, 1, 11) > 0) exp = EXTRACTED64(frb, 1, 11) - 1023;
384 if (EXTRACTED64(frb, 1, 11) == 0) exp = -1022;
385 if (EXTRACTED64(frb, 1, 11) > 0) { /* normal */
386 frac = BIT64(1) | INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
387 frac64 = 0;
388 }
389 if (EXTRACTED64(frb, 1, 11) == 0) { /* denorm */
390 frac = INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
391 frac64 = 0;
392 }
393 gbit = 0, rbit = 0, xbit = 0;
394 for (i = 1; i <= 63 - exp; i++) {
395 xbit = rbit | xbit;
396 rbit = gbit;
397 gbit = frac64;
398 frac64 = EXTRACTED64(frac, 63, 63);
399 frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63);
400 }
401 Round_Integer(processor, sign, &frac, &frac64, gbit, rbit, xbit, round_mode);
402 if (sign == 1) { /* frac[0:64] = ~frac[0:64] + 1 */
403 frac = ~frac;
404 frac64 ^= 1;
405 frac += (frac64 ? 1 : 0);
406 frac64 = (frac64 + 1) & 0x1;
407 }
408 if (tgt_precision == 32 /* can ignore frac64 in compare */
409 && (signed64)frac > (signed64)MASK64(33+1, 63)/*2^31-1 >>1*/)
410 goto Large_Operand;
411 if (tgt_precision == 64 /* can ignore frac64 in compare */
412 && (signed64)frac > (signed64)MASK64(1+1, 63)/*2^63-1 >>1*/)
413 goto Large_Operand;
414 if (tgt_precision == 32 /* can ignore frac64 in compare */
415 && (signed64)frac < (signed64)MASK64(0, 32+1)/*-2^31 >>1*/)
416 goto Large_Operand;
417 if (tgt_precision == 64 /* can ignore frac64 in compare */
418 && (signed64)frac < (signed64)MASK64(0, 0+1)/*-2^63 >>1*/)
419 goto Large_Operand;
420 FPSCR_SET_XX(FPSCR & fpscr_fi);
421 if (tgt_precision == 32)
422 *frt = MASKED64(*frt, 0, 31) | (EXTRACTED64(frac, 33, 63) << 1) | frac64;
423 if (tgt_precision == 64)
424 *frt = (EXTRACTED64(frac, 1, 63) << 1) | frac64;
425 /*FPSCR[fprf] = undefined */
426 goto Done;
427 /**/
428 Infinity_Operand:
429 FPSCR_SET_FR(0);
430 FPSCR_SET_FI(0);
431 FPSCR_OR_VX(fpscr_vxcvi);
432 if ((FPSCR & fpscr_ve) == 0) {
433 if (tgt_precision == 32) {
434 if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7FFFFFFF;
435 if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
436 }
437 else {
438 if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/
439 if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
440 }
441 /* FPSCR[FPRF] = undefined */
442 }
443 goto Done;
444 /**/
445 SNaN_Operand:
446 FPSCR_SET_FR(0);
447 FPSCR_SET_FI(0);
448 FPSCR_OR_VX(fpscr_vxsnan | fpscr_vxcvi);
449 if ((FPSCR & fpscr_ve) == 0) {
450 if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
451 if (tgt_precision == 64) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
452 /* FPSCR[fprf] = undefined */
453 }
454 goto Done;
455 /**/
456 QNaN_Operand:
457 FPSCR_SET_FR(0);
458 FPSCR_SET_FI(0);
459 FPSCR_OR_VX(fpscr_vxcvi);
460 if ((FPSCR & fpscr_ve) == 0) {
461 if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
462 if (tgt_precision == 64) *frt = BIT64(0);/*0x8000_0000_0000_0000*/
463 /* FPSCR[fprf] = undefined */
464 }
465 goto Done;
466 /**/
467 Large_Operand:
468 FPSCR_SET_FR(0);
469 FPSCR_SET_FI(0);
470 FPSCR_OR_VX(fpscr_vxcvi);
471 if ((FPSCR & fpscr_ve) == 0) {
472 if (tgt_precision == 32) {
473 if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7fffffff;
474 if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
475 }
476 else {
477 if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/
478 if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
479 }
480 /* FPSCR[fprf] = undefined */
481 }
482 /**/
483 Done:
484
485
486 # extract out raw fields of a FP number
487 int::function::sign:unsigned64 FRS
488 return (MASKED64(FRS, 0, 0)
489 ? -1
490 : 1);
491 int::function::biased_exp:unsigned64 frs, int single
492 if (single)
493 return EXTRACTED64(frs, 1, 8);
494 else
495 return EXTRACTED64(frs, 1, 11);
496 unsigned64::function::fraction:unsigned64 frs, int single
497 if (single)
498 return EXTRACTED64(frs, 9, 31);
499 else
500 return EXTRACTED64(frs, 12, 63);
501
502 # a number?, each of the below return +1 or -1 (based on sign bit)
503 # if true.
504 int::function::is_nor:unsigned64 frs, int single
505 int exp = biased_exp(frs, single);
506 return (exp >= 1
507 && exp <= (single ? 254 : 2046));
508 int::function::is_zero:unsigned64 FRS
509 return (MASKED64(FRS, 1, 63) == 0
510 ? sign(FRS)
511 : 0);
512 int::function::is_den:unsigned64 frs, int single
513 int exp = biased_exp(frs, single);
514 unsigned64 frac = fraction(frs, single);
515 return (exp == 0 && frac != 0
516 ? sign(frs)
517 : 0);
518 int::function::is_inf:unsigned64 frs, int single
519 int exp = biased_exp(frs, single);
520 int frac = fraction(frs, single);
521 return (exp == (single ? 255 : 2047) && frac == 0
522 ? sign(frs)
523 : 0);
524 int::function::is_NaN:unsigned64 frs, int single
525 int exp = biased_exp(frs, single);
526 int frac = fraction(frs, single);
527 return (exp == (single ? 255 : 2047) && frac != 0
528 ? sign(frs)
529 : 0);
530 int::function::is_SNaN:unsigned64 frs, int single
531 return (is_NaN(frs, single)
532 && !(frs & (single ? MASK64(9, 9) : MASK64(12, 12)))
533 ? sign(frs)
534 : 0);
535 int::function::is_QNaN:unsigned64 frs, int single
536 return (is_NaN(frs, single) && !is_SNaN(frs, single));
537 int::function::is_less_than:unsigned64 *fra, unsigned64 *frb
538 return *(double*)fra < *(double*)frb;
539 int::function::is_greater_than:unsigned64 *fra, unsigned64 *frb
540 return *(double*)fra > *(double*)frb;
541 int::function::is_equan_to:unsigned64 *fra, unsigned64 *frb
542 return *(double*)fra == *(double*)frb;
543
544
545 # which quiet nan should become the result
546 unsigned64::function::select_qnan:unsigned64 fra, unsigned64 frb, unsigned64 frc, int instruction_is_frsp, int generate_qnan, int single
547 unsigned64 frt = 0;
548 if (is_NaN(fra, single))
549 frt = fra;
550 else if (is_NaN(frb, single))
551 if (instruction_is_frsp)
552 frt = MASKED64(frb, 0, 34);
553 else
554 frt = frb;
555 else if (is_NaN(frc, single))
556 frt = frc;
557 else if (generate_qnan)
558 frt = MASK64(1, 12); /* 0x7FF8_0000_0000_0000 */
559 else
560 error("select_qnan - default reached\n");
561 return frt;
562
563
564 # detect invalid operation
565 int::function::is_invalid_operation:cpu *processor, unsigned_word cia, unsigned64 fra, unsigned64 frb, fpscreg check, int single, int negate
566 int fail = 0;
567 if ((check & fpscr_vxsnan)
568 && (is_SNaN(fra, single) || is_SNaN(frb, single))) {
569 FPSCR_OR_VX(fpscr_vxsnan);
570 fail = 1;
571 }
572 if ((check & fpscr_vxisi)
573 && (is_inf(fra, single) && is_inf(frb, single))
574 && ((negate && sign(fra) != sign(frb))
575 || (!negate && sign(fra) == sign(frb)))) {
576 /*FIXME: don't handle inf-inf VS inf+-inf */
577 FPSCR_OR_VX(fpscr_vxisi);
578 fail = 1;
579 }
580 if ((check & fpscr_vxidi)
581 && (is_inf(fra, single) && is_inf(frb, single))) {
582 FPSCR_OR_VX(fpscr_vxidi);
583 fail = 1;
584 }
585 if ((check & fpscr_vxzdz)
586 && (is_zero(fra) && is_zero(frb))) {
587 FPSCR_OR_VX(fpscr_vxzdz);
588 fail = 1;
589 }
590 if ((check & fpscr_vximz)
591 && (is_zero(fra) && is_inf(frb, single))) {
592 FPSCR_OR_VX(fpscr_vximz);
593 fail = 1;
594 }
595 if ((check & fpscr_vxvc)
596 && (is_NaN(fra, single) || is_NaN(frb, single))) {
597 FPSCR_OR_VX(fpscr_vxvc);
598 fail = 1;
599 }
600 if ((check & fpscr_vxsoft)) {
601 FPSCR_OR_VX(fpscr_vxsoft);
602 fail = 1;
603 }
604 if ((check & fpscr_vxsqrt)
605 && sign(fra) < 0) {
606 FPSCR_OR_VX(fpscr_vxsqrt);
607 fail = 1;
608 }
609 /* if ((check && fpscr_vxcvi) {
610 && (is_inf(fra, single) || is_NaN(fra, single) || is_large(fra, single)))
611 FPSCR_OR_VX(fpscr_vxcvi);
612 fail = 1;
613 }
614 */
615 return fail;
616
617
618
619
620
621 # handle case of invalid operation
622 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
623 if (FPSCR & fpscr_ve) {
624 /* invalid operation exception enabled */
625 /* FRT unchaged */
626 FPSCR_SET_FR(0);
627 FPSCR_SET_FI(0);
628 /* fpscr_FPRF unchanged */
629 }
630 else {
631 /* invalid operation exception disabled */
632 if (instruction_is_convert_to_64bit) {
633 error("oopsi");
634 }
635 else if (instruction_is_convert_to_32bit) {
636 error("oopsi");
637 }
638 else { /* arrith, frsp */
639 *frt = select_qnan(fra, frb, frc,
640 instruction_is_frsp, 0/*generate*/, single);
641 FPSCR_SET_FR(0);
642 FPSCR_SET_FI(0);
643 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
644 }
645 }
646
647
648
649
650 #
651 # I.2.4.1 Branch Instructions
652 #
653 0.18,6.LI,30.AA,31.LK:I:t::Branch
654 *603:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
655 *603e:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
656 *604:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
657 if (AA) NIA = IEA(EXTS(LI_0b00));
658 else NIA = IEA(CIA + EXTS(LI_0b00));
659 if (LK) LR = (spreg)CIA+4;
660 0.16,6.BO,11.BI,16.BD,30.AA,31.LK:B:t::Branch Conditional
661 *603:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
662 *603e:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
663 *604:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
664 int M, ctr_ok, cond_ok;
665 if (is_64bit_implementation && is_64bit_mode) M = 0;
666 else M = 32;
667 if (!BO{2}) CTR = CTR - 1;
668 ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != (BO{3}));
669 cond_ok = BO{0} || ((CR{BI}) == (BO{1}));
670 if (ctr_ok && cond_ok)
671 if (AA) NIA = IEA(EXTS(BD_0b00));
672 else NIA = IEA(CIA + EXTS(BD_0b00));
673 if (LK) LR = (spreg)IEA(CIA + 4);
674 0.19,6.BO,11.BI,16./,21.16,31.LK:XL:t::Branch Conditional to Link Register
675 *603:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
676 *603e:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
677 *604:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
678 int M, ctr_ok, cond_ok;
679 if (is_64bit_implementation && is_64bit_mode) M = 0;
680 else M = 32;
681 if (!BO{2}) CTR = CTR - 1;
682 ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != BO{3});
683 cond_ok = BO{0} || (CR{BI} == BO{1});
684 if (ctr_ok && cond_ok) NIA = IEA(LR_0b00);
685 if (LK) LR = (spreg)IEA(CIA + 4);
686 0.19,6.BO,11.BI,16./,21.528,31.LK:XL:t::Branch Conditional to Count Register
687 *603:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
688 *603e:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
689 *604:PPC_FUNCTION_UNIT_BPU, PPC_FUNCTION_UNIT_BPU, 1, 1, 0
690 int cond_ok;
691 cond_ok = BO{0} || (CR{BI} == BO{1});
692 if (cond_ok) NIA = IEA(CTR_0b00);
693 if (LK) LR = (spreg)IEA(CIA + 4);
694
695 #
696 # I.2.4.2 System Call Instruction
697 #
698 0.17,6./,11./,16./,30.1,31./:SC:t::System Call
699 system_call_interrupt(processor, cia);
700
701 #
702 # I.2.4.3 Condition Register Logical Instructions
703 #
704 0.19,6.BT,11.BA,16.BB,21.257,31./:XL::crand:Condition Register AND
705 BLIT32(CR, BT, CR{BA} && CR{BB});
706 0.19,6.BT,11.BA,16.BB,21.449,31./:XL::cror:Condition Register OR
707 BLIT32(CR, BT, CR{BA} || CR{BB});
708 0.19,6.BT,11.BA,16.BB,21.193,31./:XL::crxor:Condition Register XOR
709 BLIT32(CR, BT, CR{BA} != CR{BB});
710 0.19,6.BT,11.BA,16.BB,21.225,31./:XL::crnand:Condition Register NAND
711 BLIT32(CR, BT, !(CR{BA} && CR{BB}));
712 0.19,6.BT,11.BA,16.BB,21.33,31./:XL::crnor:Condition Register NOR
713 BLIT32(CR, BT, !(CR{BA} || CR{BB}));
714 0.19,6.BT,11.BA,16.BB,21.289,31./:XL::creqv:Condition Register Equivalent
715 BLIT32(CR, BT, CR{BA} == CR{BB});
716 0.19,6.BT,11.BA,16.BB,21.129,31./:XL::crandc:Condition Register AND with Complement
717 BLIT32(CR, BT, CR{BA} && !CR{BB});
718 0.19,6.BT,11.BA,16.BB,21.417,31./:XL::crorc:Condition Register OR with Complement
719 BLIT32(CR, BT, CR{BA} || !CR{BB});
720
721 #
722 # I.2.4.4 Condition Register Field Instruction
723 #
724 0.19,6.BF,9./,11.BFA,14./,16./,21.0,31./:XL:::Move Condition Register Field
725 MBLIT32(CR, 4*BF, 4*BF+3, EXTRACTED32(CR, 4*BFA, 4*BFA+3));
726
727
728 #
729 # I.3.3.2 Fixed-Point Load Instructions
730 #
731
732 0.34,6.RT,11.RA,16.D:D:::Load Byte and Zero
733 unsigned_word b;
734 unsigned_word EA;
735 if (RA == 0) b = 0;
736 else b = *rA;
737 EA = b + EXTS(D);
738 *rT = MEM(unsigned, EA, 1);
739 0.31,6.RT,11.RA,16.RB,21.87,31./:X:::Load Byte and Zero Indexed
740 unsigned_word b;
741 unsigned_word EA;
742 if (RA == 0) b = 0;
743 else b = *rA;
744 EA = b + *rB;
745 *rT = MEM(unsigned, EA, 1);
746 0.35,6.RT,11.RA,16.D:D:::Load Byte and Zero with Update
747 unsigned_word EA;
748 if (RA == 0 || RA == RT)
749 program_interrupt(processor, cia,
750 illegal_instruction_program_interrupt);
751 EA = *rA + EXTS(D);
752 *rT = MEM(unsigned, EA, 1);
753 *rA = EA;
754 0.31,6.RT,11.RA,16.RB,21.119,31./:X:::Load Byte and Zero with Update Indexed
755 unsigned_word EA;
756 if (RA == 0 || RA == RT)
757 program_interrupt(processor, cia,
758 illegal_instruction_program_interrupt);
759 EA = *rA + *rB;
760 *rT = MEM(unsigned, EA, 1);
761 *rA = EA;
762
763 0.40,6.RT,11.RA,16.D:D:::Load Halfword and Zero
764 unsigned_word b;
765 unsigned_word EA;
766 if (RA == 0) b = 0;
767 else b = *rA;
768 EA = b + EXTS(D);
769 *rT = MEM(unsigned, EA, 2);
770 0.31,6.RT,11.RA,16.RB,21.279,31./:X:::Load Halfword and Zero Indexed
771 unsigned_word b;
772 unsigned_word EA;
773 if (RA == 0) b = 0;
774 else b = *rA;
775 EA = b + *rB;
776 *rT = MEM(unsigned, EA, 2);
777 0.41,6.RT,11.RA,16.D:D:::Load Halfword and Zero with Update
778 unsigned_word EA;
779 if (RA == 0 || RA == RT)
780 program_interrupt(processor, cia,
781 illegal_instruction_program_interrupt);
782 EA = *rA + EXTS(D);
783 *rT = MEM(unsigned, EA, 2);
784 *rA = EA;
785 0.31,6.RT,11.RA,16.RB,21.311,31./:X:::Load Halfword and Zero with Update Indexed
786 unsigned_word EA;
787 if (RA == 0 || RA == RT)
788 program_interrupt(processor, cia,
789 illegal_instruction_program_interrupt);
790 EA = *rA + *rB;
791 *rT = MEM(unsigned, EA, 2);
792 *rA = EA;
793
794 0.42,6.RT,11.RA,16.D:D:::Load Halfword Algebraic
795 unsigned_word b;
796 unsigned_word EA;
797 if (RA == 0) b = 0;
798 else b = *rA;
799 EA = b + EXTS(D);
800 *rT = MEM(signed, EA, 2);
801 0.31,6.RT,11.RA,16.RB,21.343,31./:X:::Load Halfword Algebraic Indexed
802 unsigned_word b;
803 unsigned_word EA;
804 if (RA == 0) b = 0;
805 else b = *rA;
806 EA = b + *rB;
807 *rT = MEM(signed, EA, 2);
808 0.43,6.RT,11.RA,16.D:D:::Load Halfword Algebraic with Update
809 unsigned_word EA;
810 if (RA == 0 || RA == RT)
811 program_interrupt(processor, cia,
812 illegal_instruction_program_interrupt);
813 EA = *rA + EXTS(D);
814 *rT = MEM(signed, EA, 2);
815 0.31,6.RT,11.RA,16.RB,21.375,31./:X:::Load Halfword Algebraic with Update Indexed
816 unsigned_word EA;
817 if (RA == 0 || RA == RT)
818 program_interrupt(processor, cia,
819 illegal_instruction_program_interrupt);
820 EA = *rA + *rB;
821 *rT = MEM(signed, EA, 2);
822 *rA = EA;
823
824 0.32,6.RT,11.RA,16.D:D:::Load Word and Zero
825 unsigned_word b;
826 unsigned_word EA;
827 if (RA == 0) b = 0;
828 else b = *rA;
829 EA = b + EXTS(D);
830 *rT = MEM(unsigned, EA, 4);
831 0.31,6.RT,11.RA,16.RB,21.23,31./:X:::Load Word and Zero Indexed
832 unsigned_word b;
833 unsigned_word EA;
834 if (RA == 0) b = 0;
835 else b = *rA;
836 EA = b + *rB;
837 *rT = MEM(unsigned, EA, 4);
838 0.33,6.RT,11.RA,16.D:D:::Load Word and Zero with Update
839 unsigned_word EA;
840 if (RA == 0 || RA == RT)
841 program_interrupt(processor, cia,
842 illegal_instruction_program_interrupt);
843 EA = *rA + EXTS(D);
844 *rT = MEM(unsigned, EA, 4);
845 *rA = EA;
846 0.31,6.RT,11.RA,16.RB,21.55,31./:X:::Load Word and Zero with Update Indexed
847 unsigned_word EA;
848 if (RA == 0 || RA == RT)
849 program_interrupt(processor, cia,
850 illegal_instruction_program_interrupt);
851 EA = *rA + *rB;
852 *rT = MEM(unsigned, EA, 4);
853 *rA = EA;
854
855 0.58,6.RT,11.RA,16.DS,30.2:DS:64::Load Word Algebraic
856 # unsigned_word b;
857 # unsigned_word EA;
858 # if (RA == 0) b = 0;
859 # else b = *rA;
860 # EA = b + EXTS(DS_0b00);
861 # *rT = MEM(signed, EA, 4);
862 0.31,6.RT,11.RA,16.RB,21.341,31./:X:64::Load Word Algebraic Indexed
863 # unsigned_word b;
864 # unsigned_word EA;
865 # if (RA == 0) b = 0;
866 # else b = *rA;
867 # EA = b + *rB;;
868 # *rT = MEM(signed, EA, 4);
869 0.31,6.RT,11.RA,16.RB,21.373,31./:X:64::Load Word Algebraic with Update Indexed
870 # unsigned_word EA;
871 # if (RA == 0 || RA == RT)
872 # program_interrupt(processor, cia
873 # illegal_instruction_program_interrupt);
874 # EA = *rA + *rB;
875 # *rT = MEM(signed, EA, 4);
876 # *rA = EA;
877
878 0.58,6.RT,11.RA,16.DS,30.0:DS:64::Load Doubleword
879 # unsigned_word b;
880 # unsigned_word EA;
881 # if (RA == 0) b = 0;
882 # else b = *rA;
883 # EA = b + EXTS(DS_0b00);
884 # *rT = MEM(unsigned, EA, 8);
885 0.31,6.RT,11.RA,16.RB,21.21,31./:X:64::Load Doubleword Indexed
886 # unsigned_word b;
887 # unsigned_word EA;
888 # if (RA == 0) b = 0;
889 # else b = *rA;
890 # EA = b + *rB;
891 # *rT = MEM(unsigned, EA, 8);
892 0.58,6.RT,11.RA,16.DS,30.1:DS:64::Load Doubleword with Update
893 # unsigned_word EA;
894 # if (RA == 0 || RA == RT)
895 # program_interrupt(processor, cia
896 # illegal_instruction_program_interrupt);
897 # EA = *rA + EXTS(DS_0b00);
898 # *rT = MEM(unsigned, EA, 8);
899 # *rA = EA;
900 0.31,6.RT,11.RA,16.RB,21.53,31./:DS:64::Load Doubleword with Update Indexed
901 # unsigned_word EA;
902 # if (RA == 0 || RA == RT)
903 # program_interrupt(processor, cia
904 # illegal_instruction_program_interrupt);
905 # EA = *rA + *rB;
906 # *rT = MEM(unsigned, EA, 8);
907 # *rA = EA;
908
909
910
911 #
912 # I.3.3.3 Fixed-Point Store Instructions
913 #
914
915 0.38,6.RS,11.RA,16.D:D:::Store Byte
916 unsigned_word b;
917 unsigned_word EA;
918 if (RA == 0) b = 0;
919 else b = *rA;
920 EA = b + EXTS(D);
921 STORE(EA, 1, *rS);
922 0.31,6.RS,11.RA,16.RB,21.215,31./:X:::Store Byte Indexed
923 unsigned_word b;
924 unsigned_word EA;
925 if (RA == 0) b = 0;
926 else b = *rA;
927 EA = b + *rB;
928 STORE(EA, 1, *rS);
929 0.39,6.RS,11.RA,16.D:D:::Store Byte with Update
930 unsigned_word EA;
931 if (RA == 0)
932 program_interrupt(processor, cia,
933 illegal_instruction_program_interrupt);
934 EA = *rA + EXTS(D);
935 STORE(EA, 1, *rS);
936 *rA = EA;
937 0.31,6.RS,11.RA,16.RB,21.247,31./:X:::Store Byte with Update Indexed
938 unsigned_word EA;
939 if (RA == 0)
940 program_interrupt(processor, cia,
941 illegal_instruction_program_interrupt);
942 EA = *rA + *rB;
943 STORE(EA, 1, *rS);
944 *rA = EA;
945
946 0.44,6.RS,11.RA,16.D:D:::Store Half Word
947 unsigned_word b;
948 unsigned_word EA;
949 if (RA == 0) b = 0;
950 else b = *rA;
951 EA = b + EXTS(D);
952 STORE(EA, 2, *rS);
953 0.31,6.RS,11.RA,16.RB,21.407,31./:X:::Store Half Word Indexed
954 unsigned_word b;
955 unsigned_word EA;
956 if (RA == 0) b = 0;
957 else b = *rA;
958 EA = b + *rB;
959 STORE(EA, 2, *rS);
960 0.45,6.RS,11.RA,16.D:D:::Store Half Word with Update
961 unsigned_word EA;
962 if (RA == 0)
963 program_interrupt(processor, cia,
964 illegal_instruction_program_interrupt);
965 EA = *rA + EXTS(D);
966 STORE(EA, 2, *rS);
967 *rA = EA;
968 0.31,6.RS,11.RA,16.RB,21.439,31./:X:::Store Half Word with Update Indexed
969 unsigned_word EA;
970 if (RA == 0)
971 program_interrupt(processor, cia,
972 illegal_instruction_program_interrupt);
973 EA = *rA + *rB;
974 STORE(EA, 2, *rS);
975 *rA = EA;
976
977 0.36,6.RS,11.RA,16.D:D:::Store Word
978 unsigned_word b;
979 unsigned_word EA;
980 if (RA == 0) b = 0;
981 else b = *rA;
982 EA = b + EXTS(D);
983 STORE(EA, 4, *rS);
984 0.31,6.RS,11.RA,16.RB,21.151,31./:X:::Store Word Indexed
985 unsigned_word b;
986 unsigned_word EA;
987 if (RA == 0) b = 0;
988 else b = *rA;
989 EA = b + *rB;
990 STORE(EA, 4, *rS);
991 0.37,6.RS,11.RA,16.D:D:::Store Word with Update
992 unsigned_word EA;
993 if (RA == 0)
994 program_interrupt(processor, cia,
995 illegal_instruction_program_interrupt);
996 EA = *rA + EXTS(D);
997 STORE(EA, 4, *rS);
998 *rA = EA;
999 0.31,6.RS,11.RA,16.RB,21.183,31./:X:::Store Word with Update Indexed
1000 unsigned_word EA;
1001 if (RA == 0)
1002 program_interrupt(processor, cia,
1003 illegal_instruction_program_interrupt);
1004 EA = *rA + *rB;
1005 STORE(EA, 4, *rS);
1006 *rA = EA;
1007
1008 0.62,6.RS,11.RA,16.DS,30.0:DS:64::Store Doubleword
1009 # unsigned_word b;
1010 # unsigned_word EA;
1011 # if (RA == 0) b = 0;
1012 # else b = *rA;
1013 # EA = b + EXTS(DS_0b00);
1014 # STORE(EA, 8, *rS);
1015 0.31,6.RS,11.RA,16.RB,21.149,31./:X:64::Store Doubleword Indexed
1016 # unsigned_word b;
1017 # unsigned_word EA;
1018 # if (RA == 0) b = 0;
1019 # else b = *rA;
1020 # EA = b + *rB;
1021 # STORE(EA, 8, *rS);
1022 0.62,6.RS,11.RA,16.DS,30.1:DS:64::Store Doubleword with Update
1023 # unsigned_word EA;
1024 # if (RA == 0)
1025 # program_interrupt(processor, cia
1026 # illegal_instruction_program_interrupt);
1027 # EA = *rA + EXTS(DS_0b00);
1028 # STORE(EA, 8, *rS);
1029 # *rA = EA;
1030 0.31,6.RS,11.RA,16.RB,21.181,31./:X:64::Store Doubleword with Update Indexed
1031 # unsigned_word EA;
1032 # if (RA == 0)
1033 # program_interrupt(processor, cia
1034 # illegal_instruction_program_interrupt);
1035 # EA = *rA + *rB;
1036 # STORE(EA, 8, *rS);
1037 # *rA = EA;
1038
1039
1040 #
1041 # I.3.3.4 Fixed-Point Load and Store with Byte Reversal Instructions
1042 #
1043
1044 0.31,6.RT,11.RA,16.RB,21.790,31./:X:::Load Halfword Byte-Reverse Indexed
1045 unsigned_word b;
1046 unsigned_word EA;
1047 if (RA == 0) b = 0;
1048 else b = *rA;
1049 EA = b + *rB;
1050 *rT = SWAP_2(MEM(unsigned, EA, 2));
1051 0.31,6.RT,11.RA,16.RB,21.534,31./:X:::Load Word Byte-Reverse Indexed
1052 unsigned_word b;
1053 unsigned_word EA;
1054 if (RA == 0) b = 0;
1055 else b = *rA;
1056 EA = b + *rB;
1057 *rT = SWAP_4(MEM(unsigned, EA, 4));
1058
1059 0.31,6.RS,11.RA,16.RB,21.918,31./:X:::Store Half Word Byte-Reversed Indexed
1060 unsigned_word b;
1061 unsigned_word EA;
1062 if (RA == 0) b = 0;
1063 else b = *rA;
1064 EA = b + *rB;
1065 STORE(EA, 2, SWAP_2(*rS));
1066 0.31,6.RS,11.RA,16.RB,21.662,31./:X:::Store Word Byte-Reversed Indexed
1067 unsigned_word b;
1068 unsigned_word EA;
1069 if (RA == 0) b = 0;
1070 else b = *rA;
1071 EA = b + *rB;
1072 STORE(EA, 4, SWAP_4(*rS));
1073
1074
1075 #
1076 # I.3.3.5 Fixed-Point Load and Store Multiple Instrctions
1077 #
1078
1079 0.46,6.RT,11.RA,16.D:D:be::Load Multiple Word
1080 0.47,6.RS,11.RA,16.D:D:be::Store Multiple Word
1081
1082
1083 #
1084 # I.3.3.6 Fixed-Point Move Assist Instructions
1085 #
1086
1087 0.31,6.RT,11.RA,16.NB,21.597,31./:X:be::Load String Word Immediate
1088 0.31,6.RT,11.RA,16.RB,21.533,31./:X:be::Load String Word Indexed
1089
1090 0.31,6.RS,11.RA,16.NB,21.725,31./:X:be::Store String Word Immedate
1091 0.31,6.RS,11.RA,16.RB,21.661,31./:X:be::Store String Word Indexed
1092
1093
1094 #
1095 # I.3.3.7 Storage Synchronization Instructions
1096 #
1097 # HACK: Rather than monitor addresses looking for a reason
1098 # to cancel a reservation. This code instead keeps
1099 # a copy of the data read from memory. Before performing
1100 # a store, the memory area is checked to see if it has
1101 # been changed.
1102 0.31,6.RT,11.RA,16.RB,21.20,31./:X:::Load Word And Reserve Indexed
1103 unsigned_word b;
1104 unsigned_word EA;
1105 if (RA == 0) b = 0;
1106 else b = *rA;
1107 EA = b + *rB;
1108 RESERVE = 1;
1109 RESERVE_ADDR = real_addr(EA, 1/*is-read?*/);
1110 RESERVE_DATA = MEM(unsigned, EA, 4);
1111 *rT = RESERVE_DATA;
1112 0.31,6.RT,11.RA,16.RB,21.84,31./:X:64::Load Doubleword And Reserve Indexed
1113 unsigned_word b;
1114 unsigned_word EA;
1115 if (RA == 0) b = 0;
1116 else b = *rA;
1117 EA = b + *rB;
1118 RESERVE = 1;
1119 RESERVE_ADDR = real_addr(EA, 1/*is-read?*/);
1120 RESERVE_DATA = MEM(unsigned, EA, 8);
1121 *rT = RESERVE_DATA;
1122
1123 0.31,6.RS,11.RA,16.RB,21.150,31.1:X:::Store Word Conditional Indexed
1124 unsigned_word b;
1125 unsigned_word EA;
1126 if (RA == 0) b = 0;
1127 else b = *rA;
1128 EA = b + *rB;
1129 if (RESERVE) {
1130 if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/)
1131 && /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 4)) {
1132 STORE(EA, 4, *rS);
1133 CR_SET_XER_SO(0, cr_i_zero);
1134 }
1135 else {
1136 /* ment to randomly to store, we never do! */
1137 CR_SET_XER_SO(0, 0);
1138 }
1139 RESERVE = 0;
1140 }
1141 else {
1142 CR_SET_XER_SO(0, 0);
1143 }
1144 0.31,6.RS,11.RA,16.RB,21.214,31.1:X:64::Store Doubleword Conditional Indexed
1145 unsigned_word b;
1146 unsigned_word EA;
1147 if (RA == 0) b = 0;
1148 else b = *rA;
1149 EA = b + *rB;
1150 if (RESERVE) {
1151 if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/)
1152 && /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 8)) {
1153 STORE(EA, 8, *rS);
1154 CR_SET_XER_SO(0, cr_i_zero);
1155 }
1156 else {
1157 /* ment to randomly to store, we never do */
1158 CR_SET_XER_SO(0, 0);
1159 }
1160 RESERVE = 0;
1161 }
1162 else {
1163 CR_SET_XER_SO(0, 0);
1164 }
1165
1166 0.31,6./,11./,16./,21.598,31./:X::sync:Synchronize
1167 /* do nothing */
1168
1169
1170 #
1171 # I.3.3.9 Fixed-Point Arithmetic Instructions
1172 #
1173
1174 0.14,6.RT,11.RA,16.SI:D:T::Add Immediate
1175 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1176 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_SRU, 1, 1, 0
1177 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1178 if (RA_is_0) *rT = EXTS(SI);
1179 else *rT = *rA + EXTS(SI);
1180
1181 0.15,6.RT,11.RA,16.SI:D:::Add Immediate Shifted
1182 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1183 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_SRU, 1, 1, 0
1184 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1185 if (RA_is_0) *rT = EXTS(SI) << 16;
1186 else *rT = *rA + (EXTS(SI) << 16);
1187
1188 0.31,6.RT,11.RA,16.RB,21.OE,22.266,31.Rc:XO:::Add
1189 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1190 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_SRU, 1, 1, 0
1191 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1192 ALU_BEGIN(*rA);
1193 ALU_ADD(*rB);
1194 ALU_END(*rT, 0/*CA*/, OE, Rc);
1195
1196 0.31,6.RT,11.RA,16.RB,21.OE,22.40,31.Rc:XO:::Subtract From
1197 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1198 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1199 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1200 ALU_BEGIN(*rA);
1201 ALU_NOT;
1202 ALU_ADD(*rB);
1203 ALU_ADD(1);
1204 ALU_END(*rT, 0/*CA*/, OE, Rc);
1205
1206 0.12,6.RT,11.RA,16.SI:D:::Add Immediate Carrying
1207 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1208 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1209 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1210 ALU_BEGIN(*rA);
1211 ALU_ADD(EXTS(SI));
1212 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
1213
1214 0.13,6.RT,11.RA,16.SI:D:::Add Immediate Carrying and Record
1215 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1216 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1217 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1218 ALU_BEGIN(*rA);
1219 ALU_ADD(EXTS(SI));
1220 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 1/*Rc*/);
1221
1222 0.8,6.RT,11.RA,16.SI:D:::Subtract From Immediate Carrying
1223 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1224 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1225 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1226 ALU_BEGIN(*rA);
1227 ALU_NOT;
1228 ALU_ADD(EXTS(SI));
1229 ALU_ADD(1);
1230 ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
1231
1232 0.31,6.RT,11.RA,16.RB,21.OE,22.10,31.Rc:XO:::Add Carrying
1233 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1234 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1235 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1236 ALU_BEGIN(*rA);
1237 ALU_ADD(*rB);
1238 ALU_END(*rT, 1/*CA*/, OE, Rc);
1239
1240 0.31,6.RT,11.RA,16.RB,21.OE,22.8,31.Rc:XO:::Subtract From Carrying
1241 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1242 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1243 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1244 /* RT <- ~RA + RB + 1 === RT <- RB - RA */
1245 ALU_BEGIN(*rA);
1246 ALU_NOT;
1247 ALU_ADD(*rB);
1248 ALU_ADD(1);
1249 ALU_END(*rT, 1/*CA*/, OE, Rc);
1250
1251 0.31,6.RT,11.RA,16.RB,21.OE,22.138,31.Rc:XO:::Add Extended
1252 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1253 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1254 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1255 ALU_BEGIN(*rA);
1256 ALU_ADD(*rB);
1257 ALU_ADD_CA;
1258 ALU_END(*rT, 1/*CA*/, OE, Rc);
1259
1260 0.31,6.RT,11.RA,16.RB,21.OE,22.136,31.Rc:XO:::Subtract From Extended
1261 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1262 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1263 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1264 ALU_BEGIN(*rA);
1265 ALU_NOT;
1266 ALU_ADD(*rB);
1267 ALU_ADD_CA;
1268 ALU_END(*rT, 1/*CA*/, OE, Rc);
1269
1270 0.31,6.RT,11.RA,16./,21.OE,22.234,31.Rc:XO:::Add to Minus One Extended
1271 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1272 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1273 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1274 # ALU_BEGIN(*rA);
1275 # ALU_ADD_CA;
1276 # ALU_SUB(1);
1277 # ALU_END(*rT, 1/*CA*/, OE, Rc);
1278
1279 0.31,6.RT,11.RA,16./,21.OE,22.232,31.Rc:XO:::Subtract From Minus One Extended
1280 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1281 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1282 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1283 # ALU_BEGIN(*rA);
1284 # ALU_NOT;
1285 # ALU_ADD_CA;
1286 # ALU_SUB(1);
1287 # ALU_END(*rT, 1/*CA*/, OE, Rc);
1288
1289 0.31,6.RT,11.RA,16./,21.OE,22.202,31.Rc:XO::addze:Add to Zero Extended
1290 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1291 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1292 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1293 ALU_BEGIN(*rA);
1294 ALU_ADD_CA;
1295 ALU_END(*rT, 1/*CA*/, OE, Rc);
1296
1297 0.31,6.RT,11.RA,16./,21.OE,22.200,31.Rc:XO:::Subtract from Zero Extended
1298 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1299 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1300 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1301 ALU_BEGIN(*rA);
1302 ALU_NOT;
1303 ALU_ADD_CA;
1304 ALU_END(*rT, 1/*CA*/, OE, Rc);
1305
1306 0.31,6.RT,11.RA,16./,21.OE,22.104,31.Rc:XO:::Negate
1307 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1308 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 1, 1, 0
1309 *604:PPC_FUNCTION_UNIT_SCIU1, PPC_FUNCTION_UNIT_SCIU2, 1, 1, 0
1310 ALU_BEGIN(*rA);
1311 ALU_NOT;
1312 ALU_ADD(1);
1313 ALU_END(*rT,0/*CA*/,OE,Rc);
1314
1315 0.7,6.RT,11.RA,16.SI:D::mulli:Multiply Low Immediate
1316 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 3, 3, 0
1317 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 3, 3, 0
1318 *604:PPC_FUNCTION_UNIT_MCIU, PPC_FUNCTION_UNIT_MCIU, 3, 3, 0
1319 signed_word prod = *rA * EXTS(SI);
1320 *rT = prod;
1321
1322 0.31,6.RT,11.RA,16.RB,21.OE,22.233,31.Rc:D:64::Multiply Low Doubleword
1323
1324 0.31,6.RT,11.RA,16.RB,21.OE,22.235,31.Rc:XO::mullw:Multiply Low Word
1325 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 5, 5, 0
1326 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 5, 5, 0
1327 *604:PPC_FUNCTION_UNIT_MCIU, PPC_FUNCTION_UNIT_MCIU, 4, 4, 0
1328 signed64 a = (signed32)(*rA);
1329 signed64 b = (signed32)(*rB);
1330 signed64 prod = a * b;
1331 signed_word t = prod;
1332 *rT = *rA * *rB;
1333 if (t != prod && OE)
1334 XER |= (xer_overflow | xer_summary_overflow);
1335 CR0_COMPARE(t, 0, Rc);
1336
1337 0.31,6.RT,11.RA,16.RB,21./,22.73,31.Rc:XO:64::Multiply High Doubleword
1338
1339 0.31,6.RT,11.RA,16.RB,21./,22.75,31.Rc:XO::mulhw:Multiply High Word
1340 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 5, 5, 0
1341 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 5, 5, 0
1342 *604:PPC_FUNCTION_UNIT_MCIU, PPC_FUNCTION_UNIT_MCIU, 4, 4, 0
1343 signed64 a = (signed32)(*rA);
1344 signed64 b = (signed32)(*rB);
1345 signed64 prod = a * b;
1346 signed_word t = EXTRACTED64(prod, 0, 31);
1347 *rT = t;
1348 CR0_COMPARE(t, 0, Rc);
1349
1350 0.31,6.RT,11.RA,16.RB,21./,22.9,31.Rc:XO:64::Multiply High Doubleword Unsigned
1351
1352 0.31,6.RT,11.RA,16.RB,21./,22.11,31.Rc:XO::milhwu:Multiply High Word Unsigned
1353 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 6, 6, 0
1354 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 6, 6, 0
1355 *604:PPC_FUNCTION_UNIT_MCIU, PPC_FUNCTION_UNIT_MCIU, 4, 4, 0
1356 unsigned64 a = (unsigned32)(*rA);
1357 unsigned64 b = (unsigned32)(*rB);
1358 unsigned64 prod = a * b;
1359 signed_word t = EXTRACTED64(prod, 0, 31);
1360 *rT = t;
1361 CR0_COMPARE(t, 0, Rc);
1362
1363 0.31,6.RT,11.RA,16.RB,21.OE,22.489,31.Rc:XO:64::Divide Doubleword
1364
1365 0.31,6.RT,11.RA,16.RB,21.OE,22.491,31.Rc:XO::divw:Divide Word
1366 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 37, 37, 0
1367 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 37, 37, 0
1368 *604:PPC_FUNCTION_UNIT_MCIU, PPC_FUNCTION_UNIT_MCIU, 20, 20, 0
1369 signed64 dividend = (signed32)(*rA);
1370 signed64 divisor = (signed32)(*rB);
1371 if (divisor == 0 /* nb 0x8000..0 is sign extended */
1372 || (dividend == 0x80000000 && divisor == -1)) {
1373 if (OE)
1374 XER |= (xer_overflow | xer_summary_overflow);
1375 CR0_COMPARE(0, 0, Rc);
1376 }
1377 else {
1378 signed64 quotent = dividend / divisor;
1379 *rT = quotent;
1380 CR0_COMPARE((signed_word)quotent, 0, Rc);
1381 }
1382 0.31,6.RT,11.RA,16.RB,21.OE,22.457,31.Rc:XO:64::Divide Doubleword Unsigned
1383
1384 0.31,6.RT,11.RA,16.RB,21.OE,22.459,31.Rc:XO::divwu:Divide Word Unsigned
1385 *603:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 37, 37, 0
1386 *603e:PPC_FUNCTION_UNIT_IU, PPC_FUNCTION_UNIT_IU, 37, 37, 0
1387 *604:PPC_FUNCTION_UNIT_MCIU, PPC_FUNCTION_UNIT_MCIU, 20, 20, 0
1388 unsigned64 dividend = (unsigned32)(*rA);
1389 unsigned64 divisor = (unsigned32)(*rB);
1390 if (divisor == 0) {
1391 if (OE)
1392 XER |= (xer_overflow | xer_summary_overflow);
1393 CR0_COMPARE(0, 0, Rc);
1394 }
1395 else {
1396 unsigned64 quotent = dividend / divisor;
1397 *rT = quotent;
1398 CR0_COMPARE((signed_word)quotent, 0, Rc);
1399 }
1400
1401
1402 #
1403 # I.3.3.10 Fixed-Point Compare Instructions
1404 #
1405
1406 0.11,6.BF,9./,10.L,11.RA,16.SI:D:::Compare Immediate
1407 if (!is_64bit_mode && L)
1408 program_interrupt(processor, cia,
1409 illegal_instruction_program_interrupt);
1410 else {
1411 signed_word a;
1412 signed_word b = EXTS(SI);
1413 if (L == 0)
1414 a = EXTENDED(*rA);
1415 else
1416 a = *rA;
1417 CR_COMPARE(BF, a, b);
1418 }
1419 0.31,6.BF,9./,10.L,11.RA,16.RB,21.0,31./:X:::Compare
1420 if (!is_64bit_mode && L)
1421 program_interrupt(processor, cia,
1422 illegal_instruction_program_interrupt);
1423 else {
1424 signed_word a;
1425 signed_word b;
1426 if (L == 0) {
1427 a = EXTENDED(*rA);
1428 b = EXTENDED(*rB);
1429 }
1430 else {
1431 a = *rA;
1432 b = *rB;
1433 }
1434 CR_COMPARE(BF, a, b);
1435 }
1436 0.10,6.BF,9./,10.L,11.RA,16.UI:D:::Compare Logical Immediate
1437 if (!is_64bit_mode && L)
1438 program_interrupt(processor, cia,
1439 illegal_instruction_program_interrupt);
1440 else {
1441 unsigned_word a;
1442 unsigned_word b = UI;
1443 if (L == 0)
1444 a = MASKED(*rA, 32, 63);
1445 else
1446 a = *rA;
1447 CR_COMPARE(BF, a, b);
1448 }
1449 0.31,6.BF,9./,10.L,11.RA,16.RB,21.32,31./:X:::Compare Logical
1450 if (!is_64bit_mode && L)
1451 program_interrupt(processor, cia,
1452 illegal_instruction_program_interrupt);
1453 else {
1454 unsigned_word a;
1455 unsigned_word b;
1456 if (L == 0) {
1457 a = MASKED(*rA, 32, 63);
1458 b = MASKED(*rB, 32, 63);
1459 }
1460 else {
1461 a = *rA;
1462 b = *rB;
1463 }
1464 CR_COMPARE(BF, a, b);
1465 }
1466
1467
1468 #
1469 # I.3.3.11 Fixed-Point Trap Instructions
1470 #
1471
1472 0.2,6.TO,11.RA,16.SI:D:64::Trap Doubleword Immediate
1473 if (!is_64bit_mode)
1474 program_interrupt(processor, cia,
1475 illegal_instruction_program_interrupt);
1476 else {
1477 signed_word a = *rA;
1478 signed_word b = EXTS(SI);
1479 if ((a < b && TO{0})
1480 || (a > b && TO{1})
1481 || (a == b && TO{2})
1482 || ((unsigned_word)a < (unsigned_word)b && TO{3})
1483 || ((unsigned_word)a > (unsigned_word)b && TO{4})
1484 )
1485 program_interrupt(processor, cia,
1486 trap_program_interrupt);
1487 }
1488 0.3,6.TO,11.RA,16.SI:D:::Trap Word Immediate
1489 signed_word a = EXTENDED(*rA);
1490 signed_word b = EXTS(SI);
1491 if ((a < b && TO{0})
1492 || (a > b && TO{1})
1493 || (a == b && TO{2})
1494 || ((unsigned_word)a < (unsigned_word)b && TO{3})
1495 || ((unsigned_word)a > (unsigned_word)b && TO{4})
1496 )
1497 program_interrupt(processor, cia,
1498 trap_program_interrupt);
1499 0.31,6.TO,11.RA,16.RB,21.68,31./:X:64::Trap Doubleword
1500 if (!is_64bit_mode)
1501 program_interrupt(processor, cia,
1502 illegal_instruction_program_interrupt);
1503 else {
1504 signed_word a = *rA;
1505 signed_word b = *rB;
1506 if ((a < b && TO{0})
1507 || (a > b && TO{1})
1508 || (a == b && TO{2})
1509 || ((unsigned_word)a < (unsigned_word)b && TO{3})
1510 || ((unsigned_word)a > (unsigned_word)b && TO{4})
1511 )
1512 program_interrupt(processor, cia,
1513 trap_program_interrupt);
1514 }
1515 0.31,6.TO,11.RA,16.RB,21.4,31./:X:::Trap Word
1516 signed_word a = EXTENDED(*rA);
1517 signed_word b = EXTENDED(*rB);
1518 if (TO == 12 && rA == rB) {
1519 ITRACE(trace_breakpoint, ("breakpoint\n"));
1520 cpu_halt(processor, cia, was_trap, 0);
1521 }
1522 else if ((a < b && TO{0})
1523 || (a > b && TO{1})
1524 || (a == b && TO{2})
1525 || ((unsigned_word)a < (unsigned_word)b && TO{3})
1526 || ((unsigned_word)a > (unsigned_word)b && TO{4})
1527 )
1528 program_interrupt(processor, cia,
1529 trap_program_interrupt);
1530
1531 #
1532 # I.3.3.12 Fixed-Point Logical Instructions
1533 #
1534
1535 0.28,6.RS,11.RA,16.UI:D:::AND Immediate
1536 *rA = *rS & UI;
1537 CR0_COMPARE(*rA, 0, 1/*Rc*/);
1538 0.29,6.RS,11.RA,16.UI:D:::AND Immediate Shifted
1539 *rA = *rS & (UI << 16);
1540 CR0_COMPARE(*rA, 0, 1/*Rc*/);
1541 0.24,6.RS,11.RA,16.UI:D:::OR Immediate
1542 *rA = *rS | UI;
1543 0.25,6.RS,11.RA,16.UI:D:::OR Immediate Shifted
1544 *rA = *rS | (UI << 16);
1545 0.26,6.RS,11.RA,16.UI:D:::XOR Immediate
1546 *rA = *rS ^ UI;
1547 0.27,6.RS,11.RA,16.UI:D:::XOR Immediate Shifted
1548 *rA = *rS ^ (UI << 16);
1549 0.31,6.RS,11.RA,16.RB,21.28,31.Rc:X:::AND
1550 *rA = *rS & *rB;
1551 CR0_COMPARE(*rA, 0, Rc);
1552 0.31,6.RS,11.RA,16.RB,21.444,31.Rc:X:::OR
1553 *rA = *rS | *rB;
1554 CR0_COMPARE(*rA, 0, Rc);
1555 0.31,6.RS,11.RA,16.RB,21.316,31.Rc:X:::XOR
1556 *rA = *rS ^ *rB;
1557 CR0_COMPARE(*rA, 0, Rc);
1558 0.31,6.RS,11.RA,16.RB,21.476,31.Rc:X:::NAND
1559 *rA = ~(*rS & *rB);
1560 CR0_COMPARE(*rA, 0, Rc);
1561 0.31,6.RS,11.RA,16.RB,21.124,31.Rc:X:::NOR
1562 *rA = ~(*rS | *rB);
1563 CR0_COMPARE(*rA, 0, Rc);
1564 0.31,6.RS,11.RA,16.RB,21.284,31.Rc:X:::Equivalent
1565 # *rA = ~(*rS ^ *rB); /* A === B */
1566 # CR0_COMPARE(*rA, 0, Rc);
1567 0.31,6.RS,11.RA,16.RB,21.60,31.Rc:X:::AND with Complement
1568 *rA = *rS & ~*rB;
1569 CR0_COMPARE(*rA, 0, Rc);
1570 0.31,6.RS,11.RA,16.RB,21.412,31.Rc:X:::OR with Complement
1571 *rA = *rS | ~*rB;
1572 CR0_COMPARE(*rA, 0, Rc);
1573 0.31,6.RS,11.RA,16./,21.954,31.Rc:X::extsb:Extend Sign Byte
1574 *rA = (signed_word)(signed8)*rS;
1575 CR0_COMPARE(*rA, 0, Rc);
1576 0.31,6.RS,11.RA,16./,21.922,31.Rc:X::extsh:Extend Sign Half Word
1577 *rA = (signed_word)(signed16)*rS;
1578 CR0_COMPARE(*rA, 0, Rc);
1579 0.31,6.RS,11.RA,16./,21.986,31.Rc:X:64::Extend Sign Word
1580 # *rA = (signed_word)(signed32)*rS;
1581 # CR0_COMPARE(*rA, 0, Rc);
1582 0.31,6.RS,11.RA,16./,21.58,31.Rc:X:64::Count Leading Zeros Doubleword
1583 # int count = 0;
1584 # unsigned64 mask = BIT64(0);
1585 # unsigned64 source = *rS;
1586 # while (!(source & mask) && mask != 0) {
1587 # mask >>= 1;
1588 # count++;
1589 # }
1590 # *rA = count;
1591 # CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */
1592 0.31,6.RS,11.RA,16./,21.26,31.Rc:X:::Count Leading Zeros Word
1593 int count = 0;
1594 unsigned32 mask = BIT32(0);
1595 unsigned32 source = *rS;
1596 while (!(source & mask) && mask != 0) {
1597 mask >>= 1;
1598 count++;
1599 }
1600 *rA = count;
1601 CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */
1602
1603
1604 #
1605 # I.3.3.13 Fixed-Point Rotate and Shift Instructions
1606 #
1607
1608 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
1609 # long n = (sh_5 << 4) | sh_0_4;
1610 # unsigned_word r = ROTL64(*rS, n);
1611 # long b = (mb_5 << 4) | mb_0_4;
1612 # unsigned_word m = MASK(b, 63);
1613 # signed_word result = r & m;
1614 # *rA = result;
1615 # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
1616 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
1617 # long n = (sh_5 << 4) | sh_0_4;
1618 # unsigned_word r = ROTL64(*rS, n);
1619 # long e = (me_5 << 4) | me_0_4;
1620 # unsigned_word m = MASK(0, e);
1621 # signed_word result = r & m;
1622 # *rA = result;
1623 # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
1624 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
1625 # long n = (sh_5 << 4) | sh_0_4;
1626 # unsigned_word r = ROTL64(*rS, n);
1627 # long b = (mb_5 << 4) | mb_0_4;
1628 # unsigned_word m = MASK(0, (64-n));
1629 # signed_word result = r & m;
1630 # *rA = result;
1631 # CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
1632
1633 0.21,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M:::Rotate Left Word Immediate then AND with Mask
1634 long n = SH;
1635 unsigned32 s = *rS;
1636 unsigned32 r = ROTL32(s, n);
1637 unsigned32 m = MASK(MB+32, ME+32);
1638 signed_word result = r & m;
1639 *rA = result;
1640 CR0_COMPARE(result, 0, Rc);
1641 ITRACE(trace_alu,
1642 ("n=%d, s=0x%x, r=0x%x, m=0x%x, result=0x%x, cr=0x%x\n",
1643 n, s, r, m, result, CR));
1644
1645 0.30,6.RS,11.RA,16.RB,21.mb,27.8,31.Rc:MDS:64::Rotate Left Doubleword then Clear Left
1646 # long n = MASKED(*rB, 58, 63);
1647 # unsigned_word r = ROTL64(*rS, n);
1648 # long b = (mb_5 << 4) | mb_0_4;
1649 # unsigned_word m = MASK(b, 63);
1650 # signed_word result = r & m;
1651 # *rA = result;
1652 # CR0_COMPARE(result, 0, Rc);
1653 0.30,6.RS,11.RA,16.RB,21.me,27.9,31.Rc:MDS:64::Rotate Left Doubleword then Clear Right
1654 # long n = MASKED(*rB, 58, 63);
1655 # unsigned_word r = ROTL64(*rS, n);
1656 # long e = (me_5 << 4) | me_0_4;
1657 # unsigned_word m = MASK(0, e);
1658 # signed_word result = r & m;
1659 # *rA = result;
1660 # CR0_COMPARE(result, 0, Rc);
1661
1662 0.23,6.RS,11.RA,16.RB,21.MB,26.ME,31.Rc:M:::Rotate Left Word then AND with Mask
1663 # long n = MASKED(*rB, 59, 63);
1664 # unsigned32 r = ROTL32(*rS, n);
1665 # unsigned32 m = MASK(MB+32, ME+32);
1666 # signed_word result = r & m;
1667 # *rA = result;
1668 # CR0_COMPARE(result, 0, Rc);
1669 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
1670 # long n = (sh_5 << 4) | sh_0_4;
1671 # unsigned_word r = ROTL64(*rS, n);
1672 # long b = (mb_5 << 4) | mb_0_4;
1673 # unsigned_word m = MASK(b, (64-n));
1674 # signed_word result = (r & m) | (*rA & ~m)
1675 # *rA = result;
1676 # CR0_COMPARE(result, 0, Rc);
1677 0.20,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M::rlwimi:Rotate Left Word Immediate then Mask Insert
1678 long n = SH;
1679 unsigned32 r = ROTL32(*rS, n);
1680 unsigned32 m = MASK(MB+32, ME+32);
1681 signed_word result = (r & m) | (*rA & ~m);
1682 *rA = result;
1683 ITRACE(trace_alu, (": n=%d *rS=0x%x r=0x%x m=0x%x result=0x%x\n",
1684 n, *rS, r, m, result));
1685 CR0_COMPARE(result, 0, Rc);
1686
1687
1688 0.31,6.RS,11.RA,16.RB,21.27,31.Rc:X:64::Shift Left Doubleword
1689 0.31,6.RS,11.RA,16.RB,21.24,31.Rc:X:::Shift Left Word
1690 int n = MASKED(*rB, 59, 63);
1691 unsigned32 source = *rS;
1692 signed_word shifted;
1693 if (n < 32)
1694 shifted = (source << n);
1695 else
1696 shifted = 0;
1697 *rA = shifted;
1698 CR0_COMPARE(shifted, 0, Rc);
1699 ITRACE(trace_alu,
1700 ("n=%d, source=0x%x, shifted=0x%x\n",
1701 n, source, shifted));
1702 0.31,6.RS,11.RA,16.RB,21.539,31.Rc:X:64::Shift Right Doubleword
1703 0.31,6.RS,11.RA,16.RB,21.536,31.Rc:X:::Shift Right Word
1704 int n = MASKED(*rB, 59, 63);
1705 unsigned32 source = *rS;
1706 signed_word shifted;
1707 if (n < 32)
1708 shifted = (source >> n);
1709 else
1710 shifted = 0;
1711 *rA = shifted;
1712 CR0_COMPARE(shifted, 0, Rc);
1713 ITRACE(trace_alu, \
1714 ("n=%d, source=0x%x, shifted=0x%x\n",
1715 n, source, shifted));
1716
1717 0.31,6.RS,11.RA,16.sh_0_4,21.413,30.sh_5,31.Rc:XS:64::Shift Right Algebraic Doubleword Immediate
1718 0.31,6.RS,11.RA,16.SH,21.824,31.Rc:X:::Shift Right Algebraic Word Immediate
1719 int n = SH;
1720 signed_word r = ROTL32(*rS, /*64*/32-n);
1721 signed_word m = MASK(n+32, 63);
1722 int S = MASKED(*rS, 32, 32);
1723 signed_word shifted = (r & m) | (S ? ~m : 0);
1724 *rA = shifted;
1725 if (S && ((r & ~m) & MASK(32, 63)) != 0)
1726 XER |= xer_carry;
1727 else
1728 XER &= ~xer_carry;
1729 CR0_COMPARE(shifted, 0, Rc);
1730 0.31,6.RS,11.RA,16.RB,21.794,31.Rc:X:64::Shift Right Algebraic Doubleword
1731 0.31,6.RS,11.RA,16.RB,21.792,31.Rc:X:::Shift Right Algebraic Word
1732 int n = MASKED(*rB, 58, 63);
1733 int shift = (n >= 31 ? 31 : n);
1734 signed32 source = (signed32)*rS; /* signed to keep sign bit */
1735 signed32 shifted = source >> shift;
1736 unsigned32 mask = ((unsigned32)-1) >> (31-shift);
1737 *rA = (signed_word)shifted; /* if 64bit will sign extend */
1738 if (source < 0 && (source & mask))
1739 XER |= xer_carry;
1740 else
1741 XER &= ~xer_carry;
1742 CR0_COMPARE(shifted, 0, Rc);
1743
1744
1745 #
1746 # I.3.3.14 Move to/from System Register Instructions
1747 #
1748
1749 0.31,6.RS,11.spr,21.467,31./:XFX::mtspr %SPR, %RS:Move to Special Purpose Register
1750 int n = (spr{5:9} << 5) | spr{0:4};
1751 if (spr{0} && IS_PROBLEM_STATE(processor))
1752 program_interrupt(processor, cia,
1753 privileged_instruction_program_interrupt);
1754 else if (!spr_is_valid(n)
1755 || spr_is_readonly(n))
1756 program_interrupt(processor, cia,
1757 illegal_instruction_program_interrupt);
1758 else {
1759 spreg new_val = (spr_length(n) == 64
1760 ? *rS
1761 : MASKED(*rS, 32, 63));
1762 /* HACK - time base registers need to be updated immediatly */
1763 if (WITH_TIME_BASE) {
1764 signed64 time_base;
1765 switch (n) {
1766 case spr_tbu:
1767 cpu_set_time_base(processor,
1768 (MASKED64(cpu_get_time_base(processor), 32, 63)
1769 | INSERTED64(new_val, 0, 31)));
1770 break;
1771 case spr_tbl:
1772 cpu_set_time_base(processor,
1773 (MASKED64(cpu_get_time_base(processor), 0, 31)
1774 | INSERTED64(new_val, 32, 63)));
1775 break;
1776 case spr_dec:
1777 cpu_set_decrementer(processor, new_val);
1778 break;
1779 default:
1780 SPREG(n) = new_val;
1781 break;
1782 }
1783 }
1784 else {
1785 SPREG(n) = new_val;
1786 }
1787 }
1788 0.31,6.RT,11.spr,21.339,31./:XFX::mfspr %RT, %SPR:Move from Special Purpose Register
1789 int n = (spr{5:9} << 5) | spr{0:4};
1790 if (spr{0} && IS_PROBLEM_STATE(processor))
1791 program_interrupt(processor, cia,
1792 privileged_instruction_program_interrupt);
1793 else if (!spr_is_valid(n))
1794 program_interrupt(processor, cia,
1795 illegal_instruction_program_interrupt);
1796 else {
1797 /* HACK - some SPR's need to get their value extracted specially */
1798 *rT = SPREG(n);
1799 }
1800 0.31,6.RS,11./,12.FXM,20./,21.144,31./:XFX::mtfcr:Move to Condition Register Fields
1801 if (FXM == 0xff) {
1802 CR = *rS;
1803 }
1804 else {
1805 unsigned_word mask = 0;
1806 unsigned_word f;
1807 for (f = 0; f < 8; f++) {
1808 if (FXM & (0x80 >> f))
1809 mask |= (0xf << 4*(7-f));
1810 }
1811 CR = (MASKED(*rS, 32, 63) & mask) | (CR & ~mask);
1812 }
1813 0.31,6.BF,9./,11./,16./,21.512,31./:X:::Move to Condition Register from XER
1814 0.31,6.RT,11./,16./,21.19,31./:X:::Move From Condition Register
1815 *rT = (unsigned32)CR;
1816
1817 #
1818 # I.4.6.2 Floating-Point Load Instructions
1819 #
1820
1821 0.48,6.FRT,11.RA,16.D:D:f:lfs:Load Floating-Point Single
1822 unsigned_word b;
1823 unsigned_word EA;
1824 if (RA == 0) b = 0;
1825 else b = *rA;
1826 EA = b + EXTS(D);
1827 *frT = DOUBLE(MEM(unsigned, EA, 4));
1828 0.31,6.FRT,11.RA,16.RB,21.535,31./:X:f::Load Floating-Point Single Indexed
1829 unsigned_word b;
1830 unsigned_word EA;
1831 if (RA == 0) b = 0;
1832 else b = *rA;
1833 EA = b + *rB;
1834 *frT = DOUBLE(MEM(unsigned, EA, 4));
1835 0.49,6.FRT,11.RA,16.D:D:f::Load Floating-Point Single with Update
1836 unsigned_word EA;
1837 if (RA == 0)
1838 program_interrupt(processor, cia,
1839 illegal_instruction_program_interrupt);
1840 EA = *rA + EXTS(D);
1841 *frT = DOUBLE(MEM(unsigned, EA, 4));
1842 *rA = EA;
1843 0.31,6.FRT,11.RA,16.RB,21.576,31./:X:f::Load Floating-Point Single with Update Indexed
1844 unsigned_word EA;
1845 if (RA == 0)
1846 program_interrupt(processor, cia,
1847 illegal_instruction_program_interrupt);
1848 EA = *rA + *rB;
1849 *frT = DOUBLE(MEM(unsigned, EA, 4));
1850 *rA = EA;
1851
1852 0.50,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double
1853 unsigned_word b;
1854 unsigned_word EA;
1855 if (RA == 0) b = 0;
1856 else b = *rA;
1857 EA = b + EXTS(D);
1858 *frT = MEM(unsigned, EA, 8);
1859 0.31,6.FRT,11.RA,16.RB,21.599,31./:X:f::Load Floating-Point Double Indexed
1860 unsigned_word b;
1861 unsigned_word EA;
1862 if (RA == 0) b = 0;
1863 else b = *rA;
1864 EA = b + *rB;
1865 *frT = MEM(unsigned, EA, 8);
1866 0.51,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double with Update
1867 unsigned_word EA;
1868 if (RA == 0)
1869 program_interrupt(processor, cia,
1870 illegal_instruction_program_interrupt);
1871 EA = *rA + EXTS(D);
1872 *frT = MEM(unsigned, EA, 8);
1873 *rA = EA;
1874 0.31,6.FRT,11.RA,16.RB,21.631,31./:X:f::Load Floating-Point Double with Update Indexed
1875 unsigned_word EA;
1876 if (RA == 0)
1877 program_interrupt(processor, cia,
1878 illegal_instruction_program_interrupt);
1879 EA = *rA + *rB;
1880 *frT = MEM(unsigned, EA, 8);
1881 *rA = EA;
1882
1883
1884 #
1885 # I.4.6.3 Floating-Point Store Instructions
1886 #
1887
1888 0.52,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single
1889 unsigned_word b;
1890 unsigned_word EA;
1891 if (RA == 0) b = 0;
1892 else b = *rA;
1893 EA = b + EXTS(D);
1894 STORE(EA, 4, SINGLE(*frS));
1895 0.31,6.FRS,11.RA,16.RB,21.663,31./:X:f::Store Floating-Point Single Indexed
1896 unsigned_word b;
1897 unsigned_word EA;
1898 if (RA == 0) b = 0;
1899 else b = *rA;
1900 EA = b + *rB;
1901 STORE(EA, 4, SINGLE(*frS));
1902 0.53,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single with Update
1903 unsigned_word EA;
1904 if (RA == 0)
1905 program_interrupt(processor, cia,
1906 illegal_instruction_program_interrupt);
1907 EA = *rA + EXTS(D);
1908 STORE(EA, 4, SINGLE(*frS));
1909 *rA = EA;
1910 0.31,6.FRS,11.RA,16.RB,21.695,31./:X:f::Store Floating-Point Single with Update Indexed
1911 unsigned_word EA;
1912 if (RA == 0)
1913 program_interrupt(processor, cia,
1914 illegal_instruction_program_interrupt);
1915 EA = *rA + *rB;
1916 STORE(EA, 4, SINGLE(*frS));
1917 *rA = EA;
1918
1919 0.54,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double
1920 unsigned_word b;
1921 unsigned_word EA;
1922 if (RA == 0) b = 0;
1923 else b = *rA;
1924 EA = b + EXTS(D);
1925 STORE(EA, 8, *frS);
1926 0.31,6.FRS,11.RA,16.RB,21.727,31./:X:f::Store Floating-Point Double Indexed
1927 unsigned_word b;
1928 unsigned_word EA;
1929 if (RA == 0) b = 0;
1930 else b = *rA;
1931 EA = b + *rB;
1932 STORE(EA, 8, *frS);
1933 0.55,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double with Update
1934 unsigned_word EA;
1935 if (RA == 0)
1936 program_interrupt(processor, cia,
1937 illegal_instruction_program_interrupt);
1938 EA = *rA + EXTS(D);
1939 STORE(EA, 8, *frS);
1940 *rA = EA;
1941 0.31,6.FRS,11.RA,16.RB,21.759,31./:X:f::Store Floating-Point Double with Update Indexed
1942 unsigned_word EA;
1943 if (RA == 0)
1944 program_interrupt(processor, cia,
1945 illegal_instruction_program_interrupt);
1946 EA = *rA + *rB;
1947 STORE(EA, 8, *frS);
1948 *rA = EA;
1949
1950
1951 #
1952 # I.4.6.4 Floating-Point Move Instructions
1953 #
1954
1955 0.63,6.FRT,11./,16.FRB,21.72,31.Rc:X:f::Floating Move Register
1956 *frT = *frB;
1957 CR1_UPDATE(Rc);
1958 0.63,6.FRT,11./,16.FRB,21.40,31.Rc:X:f::Floating Negate
1959 *frT = *frB ^ BIT64(0);
1960 CR1_UPDATE(Rc);
1961 0.63,6.FRT,11./,16.FRB,21.264,31.Rc:X:f::Floating Absolute Value
1962 *frT = *frB & ~BIT64(0);
1963 CR1_UPDATE(Rc);
1964 0.63,6.FRT,11./,16.FRB,21.136,31.Rc:X:f::Floating Negative Absolute Value
1965 *frT = *frB | BIT64(0);
1966 CR1_UPDATE(Rc);
1967
1968
1969
1970 #
1971 # I.4.6.5 Floating-Point Arithmetic Instructions
1972 #
1973
1974 0.63,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadd:Floating Add
1975 FPSCR_BEGIN;
1976 if (is_invalid_operation(processor, cia,
1977 *frA, *frB,
1978 fpscr_vxsnan | fpscr_vxisi,
1979 0, /*single?*/
1980 0) /*negate?*/) {
1981 invalid_arithemetic_operation(processor, cia,
1982 frT, *frA, *frB, 0,
1983 0, /*instruction_is_frsp*/
1984 0, /*instruction_is_convert_to_64bit*/
1985 0, /*instruction_is_convert_to_32bit*/
1986 0); /*single-precision*/
1987 }
1988 else {
1989 /*HACK!*/
1990 double s = *(double*)frA + *(double*)frB;
1991 *(double*)frT = s;
1992 }
1993 FPSCR_END(Rc);
1994 0.59,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadds:Floating Add Single
1995 FPSCR_BEGIN;
1996 if (is_invalid_operation(processor, cia,
1997 *frA, *frB,
1998 fpscr_vxsnan | fpscr_vxisi,
1999 1, /*single?*/
2000 0) /*negate?*/) {
2001 invalid_arithemetic_operation(processor, cia,
2002 frT, *frA, *frB, 0,
2003 0, /*instruction_is_frsp*/
2004 0, /*instruction_is_convert_to_64bit*/
2005 0, /*instruction_is_convert_to_32bit*/
2006 1); /*single-precision*/
2007 }
2008 else {
2009 /*HACK!*/
2010 float s = *(double*)frA + *(double*)frB;
2011 *(double*)frT = s;
2012 }
2013 FPSCR_END(Rc);
2014
2015 0.63,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsub:Floating Subtract
2016 FPSCR_BEGIN;
2017 if (is_invalid_operation(processor, cia,
2018 *frA, *frB,
2019 fpscr_vxsnan | fpscr_vxisi,
2020 0, /*single?*/
2021 1) /*negate?*/) {
2022 invalid_arithemetic_operation(processor, cia,
2023 frT, *frA, *frB, 0,
2024 0, /*instruction_is_frsp*/
2025 0, /*instruction_is_convert_to_64bit*/
2026 0, /*instruction_is_convert_to_32bit*/
2027 0); /*single-precision*/
2028 }
2029 else {
2030 /*HACK!*/
2031 double s = *(double*)frA - *(double*)frB;
2032 *(double*)frT = s;
2033 }
2034 FPSCR_END(Rc);
2035 0.59,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsubs:Floating Subtract Single
2036 FPSCR_BEGIN;
2037 if (is_invalid_operation(processor, cia,
2038 *frA, *frB,
2039 fpscr_vxsnan | fpscr_vxisi,
2040 1, /*single?*/
2041 1) /*negate?*/) {
2042 invalid_arithemetic_operation(processor, cia,
2043 frT, *frA, *frB, 0,
2044 0, /*instruction_is_frsp*/
2045 0, /*instruction_is_convert_to_64bit*/
2046 0, /*instruction_is_convert_to_32bit*/
2047 1); /*single-precision*/
2048 }
2049 else {
2050 /*HACK!*/
2051 float s = *(double*)frA - *(double*)frB;
2052 *(double*)frT = s;
2053 }
2054 FPSCR_END(Rc);
2055
2056 0.63,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmul:Floating Multiply
2057 FPSCR_BEGIN;
2058 if (is_invalid_operation(processor, cia,
2059 *frA, *frC,
2060 fpscr_vxsnan | fpscr_vximz,
2061 0, /*single?*/
2062 0) /*negate?*/) {
2063 invalid_arithemetic_operation(processor, cia,
2064 frT, *frA, 0, *frC,
2065 0, /*instruction_is_frsp*/
2066 0, /*instruction_is_convert_to_64bit*/
2067 0, /*instruction_is_convert_to_32bit*/
2068 0); /*single-precision*/
2069 }
2070 else {
2071 /*HACK!*/
2072 double s = *(double*)frA * *(double*)frC;
2073 *(double*)frT = s;
2074 }
2075 FPSCR_END(Rc);
2076 0.59,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmuls:Floating Multiply Single
2077 FPSCR_BEGIN;
2078 if (is_invalid_operation(processor, cia,
2079 *frA, *frC,
2080 fpscr_vxsnan | fpscr_vximz,
2081 1, /*single?*/
2082 0) /*negate?*/) {
2083 invalid_arithemetic_operation(processor, cia,
2084 frT, *frA, 0, *frC,
2085 0, /*instruction_is_frsp*/
2086 0, /*instruction_is_convert_to_64bit*/
2087 0, /*instruction_is_convert_to_32bit*/
2088 1); /*single-precision*/
2089 }
2090 else {
2091 /*HACK!*/
2092 float s = *(double*)frA * *(double*)frC;
2093 *(double*)frT = s;
2094 }
2095 FPSCR_END(Rc);
2096
2097 0.63,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdiv:Floating Divide
2098 FPSCR_BEGIN;
2099 if (is_invalid_operation(processor, cia,
2100 *frA, *frB,
2101 fpscr_vxsnan | fpscr_vxzdz,
2102 0, /*single?*/
2103 0) /*negate?*/) {
2104 invalid_arithemetic_operation(processor, cia,
2105 frT, *frA, *frB, 0,
2106 0, /*instruction_is_frsp*/
2107 0, /*instruction_is_convert_to_64bit*/
2108 0, /*instruction_is_convert_to_32bit*/
2109 0); /*single-precision*/
2110 }
2111 else {
2112 /*HACK!*/
2113 double s = *(double*)frA / *(double*)frB;
2114 *(double*)frT = s;
2115 }
2116 FPSCR_END(Rc);
2117 0.59,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdivs:Floating Divide Single
2118 FPSCR_BEGIN;
2119 if (is_invalid_operation(processor, cia,
2120 *frA, *frB,
2121 fpscr_vxsnan | fpscr_vxzdz,
2122 1, /*single?*/
2123 0) /*negate?*/) {
2124 invalid_arithemetic_operation(processor, cia,
2125 frT, *frA, *frB, 0,
2126 0, /*instruction_is_frsp*/
2127 0, /*instruction_is_convert_to_64bit*/
2128 0, /*instruction_is_convert_to_32bit*/
2129 1); /*single-precision*/
2130 }
2131 else {
2132 /*HACK!*/
2133 float s = *(double*)frA / *(double*)frB;
2134 *(double*)frT = s;
2135 }
2136 FPSCR_END(Rc);
2137
2138 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f:fmadd:Floating Multiply-Add
2139 FPSCR_BEGIN;
2140 double product; /*HACK! - incorrectly loosing precision ... */
2141 /* compute the multiply */
2142 if (is_invalid_operation(processor, cia,
2143 *frA, *frC,
2144 fpscr_vxsnan | fpscr_vximz,
2145 0, /*single?*/
2146 0) /*negate?*/) {
2147 invalid_arithemetic_operation(processor, cia,
2148 (unsigned64*)&product, *frA, 0, *frC,
2149 0, /*instruction_is_frsp*/
2150 0, /*instruction_is_convert_to_64bit*/
2151 0, /*instruction_is_convert_to_32bit*/
2152 0); /*single-precision*/
2153 }
2154 else {
2155 /*HACK!*/
2156 product = *(double*)frA * *(double*)frC;
2157 }
2158 /* compute the add */
2159 if (is_invalid_operation(processor, cia,
2160 product, *frB,
2161 fpscr_vxsnan | fpscr_vxisi,
2162 0, /*single?*/
2163 0) /*negate?*/) {
2164 invalid_arithemetic_operation(processor, cia,
2165 frT, product, *frB, 0,
2166 0, /*instruction_is_frsp*/
2167 0, /*instruction_is_convert_to_64bit*/
2168 0, /*instruction_is_convert_to_32bit*/
2169 0); /*single-precision*/
2170 }
2171 else {
2172 /*HACK!*/
2173 double s = product + *(double*)frB;
2174 *(double*)frT = s;
2175 }
2176 FPSCR_END(Rc);
2177 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f::Floating Multiply-Add Single
2178
2179 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract
2180 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract Single
2181
2182 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add
2183 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add Single
2184
2185 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract
2186 0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract Single
2187
2188
2189 #
2190 # I.4.6.6 Floating-Point Rounding and Conversion Instructions
2191 #
2192
2193 0.63,6.FRT,11./,16.FRB,21.12,31.Rc:X:f::Floating Round to Single-Precision
2194 int sign;
2195 int exp;
2196 unsigned64 frac_grx;
2197 /* split off cases for what to do */
2198 if (EXTRACTED64(*frB, 1, 11) < 897
2199 && EXTRACTED64(*frB, 1, 63) > 0) {
2200 if ((FPSCR & fpscr_ue) == 0) goto Disabled_Exponent_Underflow;
2201 if ((FPSCR & fpscr_ue) != 0) goto Enabled_Exponent_Underflow;
2202 }
2203 if (EXTRACTED64(*frB, 1, 11) > 1150
2204 && EXTRACTED64(*frB, 1, 11) < 2047) {
2205 if ((FPSCR & fpscr_oe) == 0) goto Disabled_Exponent_Overflow;
2206 if ((FPSCR & fpscr_oe) != 0) goto Enabled_Exponent_Overflow;
2207 }
2208 if (EXTRACTED64(*frB, 1, 11) > 896
2209 && EXTRACTED64(*frB, 1, 11) < 1151) goto Normal_Operand;
2210 if (EXTRACTED64(*frB, 1, 63) == 0) goto Zero_Operand;
2211 if (EXTRACTED64(*frB, 1, 11) == 2047) {
2212 if (EXTRACTED64(*frB, 12, 63) == 0) goto Infinity_Operand;
2213 if (EXTRACTED64(*frB, 12, 12) == 1) goto QNaN_Operand;
2214 if (EXTRACTED64(*frB, 12, 12) == 0
2215 && EXTRACTED64(*frB, 13, 63) > 0) goto SNaN_Operand;
2216 }
2217 /* handle them */
2218 Disabled_Exponent_Underflow:
2219 sign = EXTRACTED64(*frB, 0, 0);
2220 if (EXTRACTED64(*frB, 1, 11) == 0) {
2221 exp = -1022;
2222 frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
2223 }
2224 if (EXTRACTED64(*frB, 1, 11) > 0) {
2225 exp = EXTRACTED64(*frB, 1, 11) - 1023;
2226 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
2227 }
2228 Denormalize_Operand:
2229 /* G|R|X == zero from above */
2230 while (exp < -126) {
2231 exp = exp - 1;
2232 frac_grx = (INSERTED64(EXTRACTED64(frac_grx, 0, 54), 1, 55)
2233 | MASKED64(frac_grx, 55, 55));
2234 }
2235 FPSCR_SET_UX(EXTRACTED64(frac_grx, 24, 55) > 0);
2236 Round_Single(processor, sign, &exp, &frac_grx);
2237 FPSCR_SET_XX(FPSCR & fpscr_fi);
2238 if (EXTRACTED64(frac_grx, 0, 52) == 0) {
2239 *frT = INSERTED64(sign, 0, 0);
2240 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
2241 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
2242 }
2243 if (EXTRACTED64(frac_grx, 0, 52) > 0) {
2244 if (EXTRACTED64(frac_grx, 0, 0) == 1) {
2245 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
2246 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
2247 }
2248 if (EXTRACTED64(frac_grx, 0, 0) == 0) {
2249 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_denormalized_number);
2250 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_denormalized_number);
2251 }
2252 /*Normalize_Operand:*/
2253 while (EXTRACTED64(frac_grx, 0, 0) == 0) {
2254 exp = exp - 1;
2255 frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1, 52), 0, 51);
2256 }
2257 *frT = (INSERTED64(sign, 0, 0)
2258 | INSERTED64(exp + 1023, 1, 11)
2259 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
2260 }
2261 goto Done;
2262 Enabled_Exponent_Underflow:
2263 FPSCR_SET_UX(1);
2264 sign = EXTRACTED64(*frB, 0, 0);
2265 if (EXTRACTED64(*frB, 1, 11) == 0) {
2266 exp = -1022;
2267 frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
2268 }
2269 if (EXTRACTED64(*frB, 1, 11) > 0) {
2270 exp = EXTRACTED64(*frB, 1, 11) - 1023;
2271 frac_grx = (BIT64(0) |
2272 INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52));
2273 }
2274 /*Normalize_Operand:*/
2275 while (EXTRACTED64(frac_grx, 0, 0) == 0) {
2276 exp = exp - 1;
2277 frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1, 52), 0, 51);
2278 }
2279 Round_Single(processor, sign, &exp, &frac_grx);
2280 FPSCR_SET_XX(FPSCR & fpscr_fi);
2281 exp = exp + 192;
2282 *frT = (INSERTED64(sign, 0, 0)
2283 | INSERTED64(exp + 1023, 1, 11)
2284 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
2285 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
2286 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
2287 goto Done;
2288 Disabled_Exponent_Overflow:
2289 FPSCR_SET_OX(1);
2290 if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
2291 if (EXTRACTED64(*frB, 0, 0) == 0) {
2292 *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
2293 FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
2294 }
2295 if (EXTRACTED64(*frB, 0, 0) == 1) {
2296 *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
2297 FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
2298 }
2299 }
2300 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_zero) {
2301 if (EXTRACTED64(*frB, 0, 0) == 0) {
2302 *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
2303 FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
2304 }
2305 if (EXTRACTED64(*frB, 0, 0) == 1) {
2306 *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
2307 FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
2308 }
2309 }
2310 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_pos_infinity) {
2311 if (EXTRACTED64(*frB, 0, 0) == 0) {
2312 *frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
2313 FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
2314 }
2315 if (EXTRACTED64(*frB, 0, 0) == 1) {
2316 *frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
2317 FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
2318 }
2319 }
2320 if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_neg_infinity) {
2321 if (EXTRACTED64(*frB, 0, 0) == 0) {
2322 *frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
2323 FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
2324 }
2325 if (EXTRACTED64(*frB, 0, 0) == 1) {
2326 *frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
2327 FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
2328 }
2329 }
2330 /* FPSCR[FR] <- undefined */
2331 FPSCR_SET_FI(1);
2332 FPSCR_SET_XX(1);
2333 goto Done;
2334 Enabled_Exponent_Overflow:
2335 sign = EXTRACTED64(*frB, 0, 0);
2336 exp = EXTRACTED64(*frB, 1, 11) - 1023;
2337 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
2338 Round_Single(processor, sign, &exp, &frac_grx);
2339 FPSCR_SET_XX(FPSCR & fpscr_fi);
2340 Enabled_Overflow:
2341 FPSCR_SET_OX(1);
2342 exp = exp - 192;
2343 *frT = (INSERTED64(sign, 0, 0)
2344 | INSERTED64(exp + 1023, 1, 11)
2345 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
2346 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
2347 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
2348 goto Done;
2349 Zero_Operand:
2350 *frT = *frB;
2351 if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
2352 if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
2353 FPSCR_SET_FR(0);
2354 FPSCR_SET_FI(0);
2355 goto Done;
2356 Infinity_Operand:
2357 *frT = *frB;
2358 if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
2359 if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
2360 FPSCR_SET_FR(0);
2361 FPSCR_SET_FI(0);
2362 goto Done;
2363 QNaN_Operand:
2364 *frT = INSERTED64(EXTRACTED64(*frB, 0, 34), 0, 34);
2365 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
2366 FPSCR_SET_FR(0);
2367 FPSCR_SET_FI(0);
2368 goto Done;
2369 SNaN_Operand:
2370 FPSCR_OR_VX(fpscr_vxsnan);
2371 if ((FPSCR & fpscr_ve) == 0) {
2372 *frT = (MASKED64(*frB, 0, 11)
2373 | BIT64(12)
2374 | MASKED64(*frB, 13, 34));
2375 FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
2376 }
2377 FPSCR_SET_FR(0);
2378 FPSCR_SET_FI(0);
2379 goto Done;
2380 Normal_Operand:
2381 sign = EXTRACTED64(*frB, 0, 0);
2382 exp = EXTRACTED64(*frB, 1, 11) - 1023;
2383 frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
2384 Round_Single(processor, sign, &exp, &frac_grx);
2385 FPSCR_SET_XX(FPSCR & fpscr_fi);
2386 if (exp > 127 && (FPSCR & fpscr_oe) == 0) goto Disabled_Exponent_Overflow;
2387 if (exp > 127 && (FPSCR & fpscr_oe) != 0) goto Enabled_Overflow;
2388 *frT = (INSERTED64(sign, 0, 0)
2389 | INSERTED64(exp + 1023, 1, 11)
2390 | INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
2391 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
2392 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
2393 goto Done;
2394 Done:
2395 0.63,6.FRT,11./,16.FRB,21.814,31.Rc:X:64,f::Floating Convert To Integer Doubleword
2396 0.63,6.FRT,11./,16.FRB,21.815,31.Rc:X:64,f::Floating Convert To Integer Doubleword with round towards Zero
2397 0.63,6.FRT,11./,16.FRB,21.14,31.Rc:X:f::Floating Convert To Integer Word
2398 0.63,6.FRT,11./,16.FRB,21.15,31.Rc:X:f:fctiwz:Floating Convert To Integer Word with round towards Zero
2399 FPSCR_BEGIN;
2400 convert_to_integer(processor, cia,
2401 frT, *frB,
2402 fpscr_rn_round_towards_zero, 32);
2403 FPSCR_END(Rc);
2404 0.63,6.FRT,11./,16.FRB,21.846,31.Rc:X:64,f::Floating Convert from Integer Doubleword
2405 int sign = EXTRACTED64(*frB, 0, 0);
2406 int exp = 63;
2407 unsigned64 frac = *frB;
2408 if (frac == 0) goto Zero_Operand;
2409 if (sign == 1) frac = ~frac + 1;
2410 while (EXTRACTED64(frac, 0, 0) == 0) {
2411 /*??? do the loop 0 times if (FRB) = max negative integer */
2412 frac = INSERTED64(EXTRACTED64(frac, 1, 63), 0, 62);
2413 exp = exp - 1;
2414 }
2415 Round_Float(processor, sign, &exp, &frac, FPSCR & fpscr_rn);
2416 if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
2417 if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
2418 *frT = (INSERTED64(sign, 0, 0)
2419 | INSERTED64(exp + 1023, 1, 11)
2420 | INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
2421 goto Done;
2422 /**/
2423 Zero_Operand:
2424 FPSCR_SET_FR(0);
2425 FPSCR_SET_FI(0);
2426 FPSCR_SET_FPRF(fpscr_rf_pos_zero);
2427 *frT = 0;
2428 goto Done;
2429 /**/
2430 Done:
2431
2432 #
2433 # I.4.6.7 Floating-Point Compare Instructions
2434 #
2435
2436 0.63,6.BF,9./,11.FRA,16.FRB,21.0,31./:X:f:fcmpu:Floating Compare Unordered
2437 FPSCR_BEGIN;
2438 unsigned c;
2439 if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
2440 c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
2441 else if (is_less_than(frA, frB))
2442 c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
2443 else if (is_greater_than(frA, frB))
2444 c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
2445 else
2446 c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
2447 FPSCR_SET_FPCC(c);
2448 CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
2449 if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0))
2450 FPSCR_OR_VX(fpscr_vxsnan);
2451 FPSCR_END(0);
2452 0.63,6.BF,9./,11.FRA,16.FRB,21.32,31./:X:f:fcmpo:Floating Compare Ordered
2453 FPSCR_BEGIN;
2454 unsigned c;
2455 if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
2456 c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
2457 else if (is_less_than(frA, frB))
2458 c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
2459 else if (is_greater_than(frA, frB))
2460 c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
2461 else
2462 c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
2463 FPSCR_SET_FPCC(c);
2464 CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
2465 if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0)) {
2466 FPSCR_OR_VX(fpscr_vxsnan);
2467 if ((FPSCR & fpscr_ve) == 0)
2468 FPSCR_OR_VX(fpscr_vxvc);
2469 }
2470 else if (is_QNaN(*frA, 0) || is_QNaN(*frB, 0)) {
2471 FPSCR_OR_VX(fpscr_vxvc);
2472 }
2473 FPSCR_END(0);
2474
2475
2476 #
2477 # I.4.6.8 Floating-Point Status and Control Register Instructions
2478 #
2479
2480 0.63,6.FRT,11./,16./,21.583,31.Rc:X:f::Move From FPSCR
2481 0.63,6.BF,9./,11.BFA,14./,16./,21.64,31./:X:f::Move to Condition Register from FPSCR
2482 0.64,6.BF,9./,11./,16.U,20./,21.134,31.Rc:X:f::Move To FPSCR Field Immediate
2483 0.63,6./,7.FLM,15./,16.FRB,21.711,31.Rc:XFL:f::Move To FPSCR Fields
2484 0.63,6.BT,11./,16./,21.70,31.Rc:X:f::Move To FPSCR Bit 0
2485 0.63,6.BT,11./,16./,21.38,31.Rc:X:f::Move To FPSCR Bit 1
2486
2487
2488 #
2489 # I.A.1.1 Floating-Point Store Instruction
2490 #
2491 0.31,6.FRS,11.RA,16.RB,21.983,31./:X:f::Store Floating-Point as Integer Word Indexed
2492
2493 #
2494 # I.A.1.2 Floating-Point Arithmetic Instructions
2495 #
2496
2497 0.63,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f::Floating Square Root
2498 0.59,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f::Floating Square Root Single
2499
2500 0.59,6.FRT,11./,16.FRB,21./,26.24,31.Rc:A:f::Floating Reciprocal Estimate Single
2501 0.63,6.FRT,11./,16.FRB,21./,26.26,31.Rc:A:f::Floating Reciprocal Square Root Estimate
2502
2503 #
2504 # I.A.1.3 Floating-Point Select Instruction
2505 #
2506
2507 0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.23,31.Rc:A:f::Floating Select
2508
2509
2510 #
2511 # II.3.2 Cache Management Instructions
2512 #
2513
2514 0.31,6./,11.RA,16.RB,21.982,31./:X::icbi:Instruction Cache Block Invalidate
2515 /* blindly flush all instruction cache entries */
2516 #if WITH_IDECODE_CACHE_SIZE
2517 cpu_flush_icache(processor);
2518 #endif
2519
2520 0.19,6./,11./,16./,21.150,31./:XL::isync:Instruction Synchronize
2521 cpu_synchronize_context(processor);
2522
2523
2524 #
2525 # II.3.2.2 Data Cache Instructions
2526 #
2527
2528 0.31,6./,11.RA,16.RB,21.278,31./:X:::Data Cache Block Touch
2529 ; /* nop for now */
2530
2531 0.31,6./,11.RA,16.RB,21.246,31./:X:::Data Cache Block Touch for Store
2532 ; /* nop for now */
2533
2534 0.31,6./,11.RA,16.RB,21.1014,31./:X:::Data Cache Block set to Zero
2535 ; /* nop for now */
2536
2537 0.31,6./,11.RA,16.RB,21.54,31./:X:::Data Cache Block Store
2538 ; /* nop for now */
2539
2540 0.31,6./,11.RA,16.RB,21.86,31./:X:::Data Cache Block Flush
2541 ; /* nop for now */
2542
2543 #
2544 # II.3.3 Envorce In-order Execution of I/O Instruction
2545 #
2546
2547 0.31,6./,11./,16./,21.854,31./:X::eieio:Enforce In-order Execution of I/O
2548 /* Since this model has no instruction overlap
2549 this instruction need do nothing */
2550
2551 #
2552 # II.4.1 Time Base Instructions
2553 #
2554
2555 0.31,6.RT,11.tbr,21.371,31./:XFX::mftb:Move From Time Base
2556 int n = (tbr{5:9} << 5) | tbr{0:4};
2557 if (n == 268) {
2558 if (is_64bit_implementation) *rT = TB;
2559 else *rT = EXTRACTED64(TB, 32, 63);
2560 }
2561 else if (n == 269) {
2562 if (is_64bit_implementation) *rT = EXTRACTED64(TB, 0, 31);
2563 else *rT = EXTRACTED64(TB, 0, 31);
2564 }
2565 else
2566 program_interrupt(processor, cia,
2567 illegal_instruction_program_interrupt);
2568
2569
2570 #
2571 # III.2.3.1 System Linkage Instructions
2572 #
2573
2574 #0.17,6./,11./,16./,30.1,31./:SC::sc:System Call
2575 0.19,6./,11./,16./,21.50,31./:XL::rfi:Return From Interrupt
2576 if (IS_PROBLEM_STATE(processor)) {
2577 program_interrupt(processor, cia,
2578 privileged_instruction_program_interrupt);
2579 }
2580 else {
2581 MSR = (MASKED(SRR1, 0, 32)
2582 | MASKED(SRR1, 37, 41)
2583 | MASKED(SRR1, 48, 63));
2584 NIA = MASKED(SRR0, 0, 61);
2585 cpu_synchronize_context(processor);
2586 }
2587
2588 #
2589 # III.3.4.1 Move to/from System Register Instructions
2590 #
2591
2592 #0.31,6.RS,11.spr,21.467,31./:XFX:::Move To Special Purpose Register
2593 #0.31,6.RT,11.spr,21.339,31./:XFX:::Move From Special Purpose Register
2594 0.31,6.RS,11./,16./,21.146,31./:X:::Move To Machine State Register
2595 if (IS_PROBLEM_STATE(processor))
2596 program_interrupt(processor, cia,
2597 privileged_instruction_program_interrupt);
2598 else
2599 MSR = *rS;
2600 0.31,6.RT,11./,16./,21.83,31./:X:::Move From Machine State Register
2601 if (IS_PROBLEM_STATE(processor))
2602 program_interrupt(processor, cia,
2603 privileged_instruction_program_interrupt);
2604 else
2605 *rT = MSR;
2606
2607
2608 #
2609 # III.4.11.1 Cache Management Instructions
2610 #
2611
2612 0.31,6./,11.RA,16.RB,21.470,31./:X::dcbi:Data Cache Block Invalidate
2613 ; /* nop for now */
2614
2615 #
2616 # III.4.11.2 Segment Register Manipulation Instructions
2617 #
2618
2619 0.31,6.RS,11./,12.SR,16./,21.210,31./:X:32:mtsr %SR,%RS:Move To Segment Register
2620 if (IS_PROBLEM_STATE(processor))
2621 program_interrupt(processor, cia,
2622 privileged_instruction_program_interrupt);
2623 else
2624 SEGREG(SR) = *rS;
2625 0.31,6.RS,11./,16.RB,21.242,31./:X:32:mtsrin %RS,%RB:Move To Segment Register Indirect
2626 if (IS_PROBLEM_STATE(processor))
2627 program_interrupt(processor, cia,
2628 privileged_instruction_program_interrupt);
2629 else
2630 SEGREG(EXTRACTED32(*rB, 0, 3)) = *rS;
2631 0.31,6.RT,11./,12.SR,16./,21.595,31./:X:32:mfsr %RT,%RS:Move From Segment Register
2632 if (IS_PROBLEM_STATE(processor))
2633 program_interrupt(processor, cia,
2634 privileged_instruction_program_interrupt);
2635 else
2636 *rT = SEGREG(SR);
2637 0.31,6.RT,11./,16.RB,21.659,31./:X:32:mfsrin %RT,%RB:Move From Segment Register Indirect
2638 if (IS_PROBLEM_STATE(processor))
2639 program_interrupt(processor, cia,
2640 privileged_instruction_program_interrupt);
2641 else
2642 *rT = SEGREG(EXTRACTED32(*rB, 0, 3));
2643
2644
2645 #
2646 # III.4.11.3 Lookaside Buffer Management Instructions (Optional)
2647 #
2648
2649 0.31,6./,11./,16.RB,21.434,31./:X:64::SLB Invalidate Entry
2650 0.31,6./,11./,16./,21.498,31./:X:64::SLB Invalidate All
2651
2652 0.31,6./,11./,16.RB,21.306,31./:X:::TLB Invalidate Entry
2653 0.31,6./,11./,16./,21.370,31./:X:::TLB Invalidate All
2654
2655 0.31,6./,11./,16./,21.566,31./:X:::TLB Sychronize
2656
2657
2658 #
2659 # III.A.1.2 External Access Instructions
2660 #
2661
2662 0.31,6.RT,11.RA,16.RB,21.310,31./:X:earwax::External Control In Word Indexed
2663 0.31,6.RS,11.RA,16.RB,21.438,31./:X:earwax::External Control Out Word Indexed
This page took 0.084915 seconds and 5 git commands to generate.