1995-11-01 19:32:38 +00:00
#
# This file is part of the program psim.
#
# Copyright (C) 1994-1995, Andrew Cagney <cagney@highland.com.au>
#
# --
#
# The pseudo-code that appears below, translated into C, was copied
# by Andrew Cagney of Moss Vale, Australia.
#
# This pseudo-code is copied by permission from the publication
# "The PowerPC Architecture: A Specification for A New Family of
# RISC Processors" (ISBN 1-55860-316-6) copyright 1993, 1994 by
# International Business Machines Corporation.
#
# THIS PERMISSION IS PROVIDED WITHOUT WARRANTY OF ANY KIND, EITHER
# EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#
# --
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# --
#
#
# Fields:
#
# 1 Instruction format as a `start-bit,content' pairs.
# the content is one of a digit, field name or `/' (aka.0)
#
# 2 Format specifier
#
# 3 Flags: 64 - 64bit only
# f - floating point enabled required
#
# 4 short name
#
# 5 Description
#
1995-11-12 14:20:39 +00:00
#
# For flags marked 'model', the fields are interpreted as follows:
#
# 1 Not used
#
# 2 Not used
#
# 3 "macro"
#
# 4 String name for model
#
# 5 Specific CPU model, must be an identifier
#
# 6 Comma separated list of functional units
1995-11-16 19:02:52 +00:00
1995-11-15 22:53:59 +00:00
# PowerPC models
1995-11-16 19:02:52 +00:00
::model:604:ppc604: PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0
::model:603e:ppc603e:PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0
::model:603:ppc603: PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0
::model:601:ppc601: PPC_UNIT_BAD, PPC_UNIT_BAD, 1, 1, 0
1995-11-12 14:20:39 +00:00
# Flags for model.h
1995-11-15 22:53:59 +00:00
::model-data:::
typedef enum _ppc_function_unit {
1995-11-16 19:02:52 +00:00
PPC_UNIT_BAD, /* unknown function unit */
PPC_UNIT_IU, /* integer unit (601/603 style) */
PPC_UNIT_SRU, /* system register unit (601/603 style) */
PPC_UNIT_SCIU1, /* 1st single cycle integer unit (604 style) */
PPC_UNIT_SCIU2, /* 2nd single cycle integer unit (604 style) */
PPC_UNIT_MCIU, /* multiple cycle integer unit (604 style) */
PPC_UNIT_FPU, /* floating point unit */
PPC_UNIT_LSU, /* load/store unit */
PPC_UNIT_BPU, /* branch unit */
1995-11-15 22:53:59 +00:00
nr_ppc_function_units
} ppc_function_unit;
1995-11-16 19:02:52 +00:00
1995-11-15 22:53:59 +00:00
/* Structure to hold timing information on a per instruction basis */
struct _model_time {
ppc_function_unit first_unit; /* first functional unit this insn could use */
ppc_function_unit last_unit; /* last functional unit this insn could use */
unsigned16 issue; /* # cycles before function unit can process other insns */
unsigned16 done; /* # cycles before insn is done */
unsigned32 flags; /* flag bits */
};
1995-11-16 19:02:52 +00:00
1995-11-15 22:53:59 +00:00
/* Flags */
#define PPC_LOAD 0x00000001 /* insn is a load */
#define PPC_STORE 0x00000002 /* insn is a store */
#define PPC_SERIALIZE 0x00000004 /* insn forces serialization */
1995-11-16 19:02:52 +00:00
1995-11-15 22:53:59 +00:00
/* Structure to hold the current state information for the simulated CPU model */
struct _model_data {
const char *name; /* model name */
const model_time *timing; /* timing information */
unsigned_word old_program_counter; /* previous PC */
unsigned nr_branches; /* # branches */
unsigned nr_units[nr_ppc_function_units]; /* function unit counts */
unsigned16 busy[nr_ppc_function_units]; /* how long until free */
};
1995-11-16 19:02:52 +00:00
1995-11-15 22:53:59 +00:00
STATIC_MODEL const char *const ppc_function_unit_name[ (int)nr_ppc_function_units ] = {
1995-11-16 19:02:52 +00:00
"unknown functional unit instruction",
"integer functional unit instruction",
"system register functional unit instruction",
"1st single cycle integer functional unit instruction",
"2nd single cycle integer functional unit instruction",
"multiple cycle integer functional unit instruction",
"floating point functional unit instruction",
"load/store functional unit instruction",
"branch functional unit instruction",
1995-11-15 22:53:59 +00:00
};
model_data *::model-function::model_create:cpu *processor
1995-11-16 19:02:52 +00:00
if (CURRENT_MODEL == MODEL_NONE) {
error("Must define a CPU model");
1995-11-15 22:53:59 +00:00
return (model_data *)0;
1995-11-16 19:02:52 +00:00
}
1995-11-15 22:53:59 +00:00
else {
model_data *model_ptr = ZALLOC(model_data);
model_ptr->name = model_name[CURRENT_MODEL];
model_ptr->timing = model_time_mapping[CURRENT_MODEL];
return model_ptr;
}
1995-11-12 14:20:39 +00:00
1995-11-15 22:53:59 +00:00
void::model-function::model_init:cpu *processor, model_data *model_ptr
1995-11-16 19:02:52 +00:00
1995-11-15 22:53:59 +00:00
void::model-function::model_halt:cpu *processor, model_data *model_ptr
1995-11-16 19:25:47 +00:00
void::model-function::model_issue:itable_index index, cpu *processor, model_data *model_ptr, unsigned_word cia
1995-11-15 22:53:59 +00:00
if (model_ptr->old_program_counter+4 != cia)
model_ptr->nr_branches++;
1995-11-16 19:02:52 +00:00
1995-11-15 22:53:59 +00:00
model_ptr->old_program_counter = cia;
model_ptr->nr_units[ (int)model_ptr->timing[ (int)index ].first_unit ]++;
1995-11-16 19:02:52 +00:00
/* Assume that any instruction we don't know about is illegal for this
cpu model */
if (model_ptr->timing[(int)index].first_unit == PPC_UNIT_BAD)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
1995-11-15 22:53:59 +00:00
model_print *::model-function::model_mon_info:model_data *model_ptr
model_print *head;
model_print *tail;
ppc_function_unit i;
1995-11-16 19:02:52 +00:00
1995-11-15 22:53:59 +00:00
head = tail = ZALLOC(model_print);
tail->count = model_ptr->nr_branches;
tail->name = "branch";
tail->suffix_plural = "es";
tail->suffix_singular = "";
1995-11-16 19:02:52 +00:00
for (i = PPC_UNIT_BAD; i < nr_ppc_function_units; i++) {
1995-11-15 22:53:59 +00:00
if (model_ptr->nr_units[i]) {
tail->next = ZALLOC(model_print);
tail = tail->next;
tail->count = model_ptr->nr_units[i];
tail->name = ppc_function_unit_name[i];
tail->suffix_plural = "s";
tail->suffix_singular = "";
}
}
1995-11-16 19:02:52 +00:00
1995-11-15 22:53:59 +00:00
tail->next = (model_print *)0;
return head;
void::model-function::model_mon_info_free:model_data *model_ptr, model_print *ptr
model_print *next;
1995-11-16 19:02:52 +00:00
1995-11-15 22:53:59 +00:00
while (ptr) {
next = ptr->next;
free((void *)ptr);
ptr = next;
}
1995-11-12 14:20:39 +00:00
1995-11-01 19:32:38 +00:00
# The following (illegal) instruction is `known' by gen and is
# called when ever an illegal instruction is encountered
::internal::illegal
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
return 0;
# The following (floating point unavailable) instruction is `known' by gen
# and is called when ever an a floating point instruction is to be
# executed but floating point is make unavailable by the MSR
::internal::floating_point_unavailable
floating_point_unavailable_interrupt(processor, cia);
return 0;
#
# Floating point support functions
#
# Convert 32bit single to 64bit double
unsigned64::function::DOUBLE:unsigned32 WORD
unsigned64 FRT;
if (EXTRACTED32(WORD, 1, 8) > 0
&& EXTRACTED32(WORD, 1, 8) < 255) {
/* normalized operand */
int not_word_1_1 = !EXTRACTED32(WORD, 1, 1); /*2.6.3 bug*/
FRT = (INSERTED64(EXTRACTED32(WORD, 0, 1), 0, 1)
| INSERTED64(not_word_1_1, 2, 2)
| INSERTED64(not_word_1_1, 3, 3)
| INSERTED64(not_word_1_1, 4, 4)
| INSERTED64(EXTRACTED32(WORD, 2, 31), 5, (63 - 29)));
}
else if (EXTRACTED32(WORD, 1, 8) == 0
&& EXTRACTED32(WORD, 9, 31) != 0) {
/* denormalized operand */
int sign = EXTRACTED32(WORD, 0, 0);
int exp = -126;
unsigned64 frac = INSERTED64(EXTRACTED32(WORD, 9, 31), 1, (52 - 29));
/* normalize the operand */
while (MASKED64(frac, 0, 0) == 0) {
frac <<= 1;
exp -= 1;
}
FRT = (INSERTED64(sign, 0, 0)
| INSERTED64(exp + 1023, 1, 11)
| INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
}
else if (EXTRACTED32(WORD, 1, 8) == 255
|| EXTRACTED32(WORD, 1, 31) == 0) {
FRT = (INSERTED64(EXTRACTED32(WORD, 0, 1), 0, 1)
| INSERTED64(EXTRACTED32(WORD, 1, 1), 2, 2)
| INSERTED64(EXTRACTED32(WORD, 1, 1), 3, 3)
| INSERTED64(EXTRACTED32(WORD, 1, 1), 4, 4)
| INSERTED64(EXTRACTED32(WORD, 2, 31), 5, (63 - 29)));
}
else {
error("DOUBLE - unknown case\n");
FRT = 0;
}
return FRT;
# Convert 64bit single to 32bit double
unsigned32::function::SINGLE:unsigned64 FRS
unsigned32 WORD;
if (EXTRACTED64(FRS, 1, 11) > 896
|| EXTRACTED64(FRS, 1, 63) == 0) {
/* no denormalization required (includes Zero/Infinity/NaN) */
WORD = (INSERTED32(EXTRACTED64(FRS, 0, 1), 0, 1)
| INSERTED32(EXTRACTED64(FRS, 5, 34), 2, 31));
}
else if (874 <= EXTRACTED64(FRS, 1, 11)
&& EXTRACTED64(FRS, 1, 11) <= 896) {
/* denormalization required */
int sign = EXTRACTED64(FRS, 0, 0);
int exp = EXTRACTED64(FRS, 1, 11) - 1023;
unsigned64 frac = (BIT64(0)
| INSERTED64(EXTRACTED64(FRS, 12, 63), 1, 52));
/* denormalize the operand */
while (exp < -126) {
frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63);
exp += 1;
}
WORD = (INSERTED32(sign, 0, 0)
| INSERTED32(0x00, 1, 8)
| INSERTED32(EXTRACTED64(frac, 1, 23), 9, 31));
}
else {
WORD = 0x0; /* ??? */
}
return WORD;
# round 64bit double to 64bit but single
void::function::Round_Single:cpu *processor, int sign, int *exp, unsigned64 *frac_grx
/* comparisons ignore u bits */
unsigned64 out;
int inc = 0;
int lsb = EXTRACTED64(*frac_grx, 23, 23);
int gbit = EXTRACTED64(*frac_grx, 24, 24);
int rbit = EXTRACTED64(*frac_grx, 25, 25);
int xbit = EXTRACTED64(*frac_grx, 26, 55) != 0;
if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
if (lsb == 1 && gbit == 1) inc = 1;
if (lsb == 0 && gbit == 1 && rbit == 1) inc = 1;
if (lsb == 0 && gbit == 1 && xbit == 1) inc = 1;
}
if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_pos_infinity) {
if (sign == 0 && gbit == 1) inc = 1;
if (sign == 0 && rbit == 1) inc = 1;
if (sign == 0 && xbit == 1) inc = 1;
}
if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_neg_infinity) {
if (sign == 1 && gbit == 1) inc = 1;
if (sign == 1 && rbit == 1) inc = 1;
if (sign == 1 && xbit == 1) inc = 1;
}
/* work out addition in low 25 bits of out */
out = EXTRACTED64(*frac_grx, 0, 23) + inc;
*frac_grx = INSERTED64(out, 0, 23);
if (out & BIT64(64 - 23 - 1 - 1)) {
*frac_grx = (BIT64(0) |
INSERTED64(EXTRACTED64(*frac_grx, 0, 22), 1, 23));
*exp = *exp + 1;
}
/* frac_grx[24:52] = 0 already */
FPSCR_SET_FR(inc);
FPSCR_SET_FI(gbit || rbit || xbit);
#
void::function::Round_Integer:cpu *processor, int sign, unsigned64 *frac, int *frac64, int gbit, int rbit, int xbit, fpscreg round_mode
int inc = 0;
if (round_mode == fpscr_rn_round_to_nearest) {
if (*frac64 == 1 && gbit == 1) inc = 1;
if (*frac64 == 0 && gbit == 1 && rbit == 1) inc = 1;
if (*frac64 == 0 && gbit == 1 && xbit == 1) inc = 1;
}
if (round_mode == fpscr_rn_round_towards_pos_infinity) {
if (sign == 0 && gbit == 1) inc = 1;
if (sign == 0 && rbit == 1) inc = 1;
if (sign == 0 && xbit == 1) inc = 1;
}
if (round_mode == fpscr_rn_round_towards_neg_infinity) {
if (sign == 1 && gbit == 1) inc = 1;
if (sign == 1 && rbit == 1) inc = 1;
if (sign == 1 && xbit == 1) inc = 1;
}
/* frac[0:64] = frac[0:64} + inc */
*frac += (*frac64 && inc ? 1 : 0);
*frac64 = (*frac64 + inc) & 0x1;
FPSCR_SET_FR(inc);
FPSCR_SET_FI(gbit | rbit | xbit);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
void::function::Round_Float:cpu *processor, int sign, int *exp, unsigned64 *frac, fpscreg round_mode
int carry_out;
int inc = 0;
int lsb = EXTRACTED64(*frac, 52, 52);
int gbit = EXTRACTED64(*frac, 53, 53);
int rbit = EXTRACTED64(*frac, 54, 54);
int xbit = EXTRACTED64(*frac, 55, 55);
if (round_mode == fpscr_rn_round_to_nearest) {
if (lsb == 1 && gbit == 1) inc = 1;
if (lsb == 0 && gbit == 1 && rbit == 1) inc = 1;
if (lsb == 0 && gbit == 1 && xbit == 1) inc = 1;
}
if (round_mode == fpscr_rn_round_towards_pos_infinity) {
if (sign == 0 && gbit == 1) inc = 1;
if (sign == 0 && rbit == 1) inc = 1;
if (sign == 0 && xbit == 1) inc = 1;
}
if (round_mode == fpscr_rn_round_towards_neg_infinity) {
if (sign == 1 && gbit == 1) inc = 1;
if (sign == 1 && rbit == 1) inc = 1;
if (sign == 1 && xbit == 1) inc = 1;
}
/* frac//carry_out = frac + inc */
*frac = (*frac >> 1) + (INSERTED64(inc, 52, 52) >> 1);
carry_out = EXTRACTED64(*frac, 0, 0);
*frac <<= 1;
if (carry_out == 1) *exp = *exp + 1;
FPSCR_SET_FR(inc);
FPSCR_SET_FI(gbit | rbit | xbit);
FPSCR_SET_XX(FPSCR & fpscr_fi);
# conversion of FP to integer
void::function::convert_to_integer:cpu *processor, unsigned_word cia, unsigned64 *frt, unsigned64 frb, fpscreg round_mode, int tgt_precision
int i;
int exp = 0;
unsigned64 frac = 0;
int frac64 = 0;
int gbit = 0;
int rbit = 0;
int xbit = 0;
int sign = EXTRACTED64(frb, 0, 0);
if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 63) == 0)
goto Infinity_Operand;
if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 0)
goto SNaN_Operand;
if (EXTRACTED64(frb, 1, 11) == 2047 && EXTRACTED64(frb, 12, 12) == 1)
goto QNaN_Operand;
if (EXTRACTED64(frb, 1, 11) > 1086) goto Large_Operand;
if (EXTRACTED64(frb, 1, 11) > 0) exp = EXTRACTED64(frb, 1, 11) - 1023;
if (EXTRACTED64(frb, 1, 11) == 0) exp = -1022;
if (EXTRACTED64(frb, 1, 11) > 0) { /* normal */
frac = BIT64(1) | INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
frac64 = 0;
}
if (EXTRACTED64(frb, 1, 11) == 0) { /* denorm */
frac = INSERTED64(EXTRACTED64(frb, 12, 63), 2, 53);
frac64 = 0;
}
gbit = 0, rbit = 0, xbit = 0;
for (i = 1; i <= 63 - exp; i++) {
xbit = rbit | xbit;
rbit = gbit;
gbit = frac64;
frac64 = EXTRACTED64(frac, 63, 63);
frac = INSERTED64(EXTRACTED64(frac, 0, 62), 1, 63);
}
Round_Integer(processor, sign, &frac, &frac64, gbit, rbit, xbit, round_mode);
if (sign == 1) { /* frac[0:64] = ~frac[0:64] + 1 */
frac = ~frac;
frac64 ^= 1;
frac += (frac64 ? 1 : 0);
frac64 = (frac64 + 1) & 0x1;
}
if (tgt_precision == 32 /* can ignore frac64 in compare */
&& (signed64)frac > (signed64)MASK64(33+1, 63)/*2^31-1 >>1*/)
goto Large_Operand;
if (tgt_precision == 64 /* can ignore frac64 in compare */
&& (signed64)frac > (signed64)MASK64(1+1, 63)/*2^63-1 >>1*/)
goto Large_Operand;
if (tgt_precision == 32 /* can ignore frac64 in compare */
&& (signed64)frac < (signed64)MASK64(0, 32+1)/*-2^31 >>1*/)
goto Large_Operand;
if (tgt_precision == 64 /* can ignore frac64 in compare */
&& (signed64)frac < (signed64)MASK64(0, 0+1)/*-2^63 >>1*/)
goto Large_Operand;
FPSCR_SET_XX(FPSCR & fpscr_fi);
if (tgt_precision == 32)
*frt = MASKED64(*frt, 0, 31) | (EXTRACTED64(frac, 33, 63) << 1) | frac64;
if (tgt_precision == 64)
*frt = (EXTRACTED64(frac, 1, 63) << 1) | frac64;
/*FPSCR[fprf] = undefined */
goto Done;
/**/
Infinity_Operand:
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
FPSCR_OR_VX(fpscr_vxcvi);
if ((FPSCR & fpscr_ve) == 0) {
if (tgt_precision == 32) {
if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7FFFFFFF;
if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
}
else {
if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/
if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
}
/* FPSCR[FPRF] = undefined */
}
goto Done;
/**/
SNaN_Operand:
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
FPSCR_OR_VX(fpscr_vxsnan | fpscr_vxcvi);
if ((FPSCR & fpscr_ve) == 0) {
if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
if (tgt_precision == 64) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
/* FPSCR[fprf] = undefined */
}
goto Done;
/**/
QNaN_Operand:
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
FPSCR_OR_VX(fpscr_vxcvi);
if ((FPSCR & fpscr_ve) == 0) {
if (tgt_precision == 32) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
if (tgt_precision == 64) *frt = BIT64(0);/*0x8000_0000_0000_0000*/
/* FPSCR[fprf] = undefined */
}
goto Done;
/**/
Large_Operand:
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
FPSCR_OR_VX(fpscr_vxcvi);
if ((FPSCR & fpscr_ve) == 0) {
if (tgt_precision == 32) {
if (sign == 0) *frt = MASKED64(*frt, 0, 31) | 0x7fffffff;
if (sign == 1) *frt = MASKED64(*frt, 0, 31) | 0x80000000;
}
else {
if (sign == 0) *frt = MASK64(1, 63); /*0x7FFF_FFFF_FFFF_FFFF*/
if (sign == 1) *frt = BIT64(0); /*0x8000_0000_0000_0000*/
}
/* FPSCR[fprf] = undefined */
}
/**/
Done:
# extract out raw fields of a FP number
int::function::sign:unsigned64 FRS
return (MASKED64(FRS, 0, 0)
? -1
: 1);
int::function::biased_exp:unsigned64 frs, int single
if (single)
return EXTRACTED64(frs, 1, 8);
else
return EXTRACTED64(frs, 1, 11);
unsigned64::function::fraction:unsigned64 frs, int single
if (single)
return EXTRACTED64(frs, 9, 31);
else
return EXTRACTED64(frs, 12, 63);
# a number?, each of the below return +1 or -1 (based on sign bit)
# if true.
int::function::is_nor:unsigned64 frs, int single
int exp = biased_exp(frs, single);
return (exp >= 1
&& exp <= (single ? 254 : 2046));
int::function::is_zero:unsigned64 FRS
return (MASKED64(FRS, 1, 63) == 0
? sign(FRS)
: 0);
int::function::is_den:unsigned64 frs, int single
int exp = biased_exp(frs, single);
unsigned64 frac = fraction(frs, single);
return (exp == 0 && frac != 0
? sign(frs)
: 0);
int::function::is_inf:unsigned64 frs, int single
int exp = biased_exp(frs, single);
int frac = fraction(frs, single);
return (exp == (single ? 255 : 2047) && frac == 0
? sign(frs)
: 0);
int::function::is_NaN:unsigned64 frs, int single
int exp = biased_exp(frs, single);
int frac = fraction(frs, single);
return (exp == (single ? 255 : 2047) && frac != 0
? sign(frs)
: 0);
int::function::is_SNaN:unsigned64 frs, int single
return (is_NaN(frs, single)
&& !(frs & (single ? MASK64(9, 9) : MASK64(12, 12)))
? sign(frs)
: 0);
int::function::is_QNaN:unsigned64 frs, int single
return (is_NaN(frs, single) && !is_SNaN(frs, single));
int::function::is_less_than:unsigned64 *fra, unsigned64 *frb
return *(double*)fra < *(double*)frb;
int::function::is_greater_than:unsigned64 *fra, unsigned64 *frb
return *(double*)fra > *(double*)frb;
int::function::is_equan_to:unsigned64 *fra, unsigned64 *frb
return *(double*)fra == *(double*)frb;
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
# which quiet nan should become the result
unsigned64::function::select_qnan:unsigned64 fra, unsigned64 frb, unsigned64 frc, int instruction_is_frsp, int generate_qnan, int single
unsigned64 frt = 0;
if (is_NaN(fra, single))
frt = fra;
else if (is_NaN(frb, single))
if (instruction_is_frsp)
frt = MASKED64(frb, 0, 34);
else
frt = frb;
else if (is_NaN(frc, single))
frt = frc;
else if (generate_qnan)
frt = MASK64(1, 12); /* 0x7FF8_0000_0000_0000 */
else
error("select_qnan - default reached\n");
return frt;
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
# detect invalid operation
int::function::is_invalid_operation:cpu *processor, unsigned_word cia, unsigned64 fra, unsigned64 frb, fpscreg check, int single, int negate
int fail = 0;
if ((check & fpscr_vxsnan)
&& (is_SNaN(fra, single) || is_SNaN(frb, single))) {
FPSCR_OR_VX(fpscr_vxsnan);
fail = 1;
}
if ((check & fpscr_vxisi)
&& (is_inf(fra, single) && is_inf(frb, single))
&& ((negate && sign(fra) != sign(frb))
|| (!negate && sign(fra) == sign(frb)))) {
/*FIXME: don't handle inf-inf VS inf+-inf */
FPSCR_OR_VX(fpscr_vxisi);
fail = 1;
}
if ((check & fpscr_vxidi)
&& (is_inf(fra, single) && is_inf(frb, single))) {
FPSCR_OR_VX(fpscr_vxidi);
fail = 1;
}
if ((check & fpscr_vxzdz)
&& (is_zero(fra) && is_zero(frb))) {
FPSCR_OR_VX(fpscr_vxzdz);
fail = 1;
}
if ((check & fpscr_vximz)
&& (is_zero(fra) && is_inf(frb, single))) {
FPSCR_OR_VX(fpscr_vximz);
fail = 1;
}
if ((check & fpscr_vxvc)
&& (is_NaN(fra, single) || is_NaN(frb, single))) {
FPSCR_OR_VX(fpscr_vxvc);
fail = 1;
}
if ((check & fpscr_vxsoft)) {
FPSCR_OR_VX(fpscr_vxsoft);
fail = 1;
}
if ((check & fpscr_vxsqrt)
&& sign(fra) < 0) {
FPSCR_OR_VX(fpscr_vxsqrt);
fail = 1;
}
/* if ((check && fpscr_vxcvi) {
&& (is_inf(fra, single) || is_NaN(fra, single) || is_large(fra, single)))
FPSCR_OR_VX(fpscr_vxcvi);
fail = 1;
}
*/
return fail;
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
# handle case of invalid operation
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
if (FPSCR & fpscr_ve) {
/* invalid operation exception enabled */
/* FRT unchaged */
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
/* fpscr_FPRF unchanged */
}
else {
/* invalid operation exception disabled */
if (instruction_is_convert_to_64bit) {
error("oopsi");
}
else if (instruction_is_convert_to_32bit) {
error("oopsi");
}
else { /* arrith, frsp */
*frt = select_qnan(fra, frb, frc,
instruction_is_frsp, 0/*generate*/, single);
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
}
}
#
# I.2.4.1 Branch Instructions
#
0.18,6.LI,30.AA,31.LK:I:t::Branch
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
*603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
*603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1995-11-01 19:32:38 +00:00
if (AA) NIA = IEA(EXTS(LI_0b00));
else NIA = IEA(CIA + EXTS(LI_0b00));
if (LK) LR = (spreg)CIA+4;
0.16,6.BO,11.BI,16.BD,30.AA,31.LK:B:t::Branch Conditional
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
*603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
*603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1995-11-01 19:32:38 +00:00
int M, ctr_ok, cond_ok;
if (is_64bit_implementation && is_64bit_mode) M = 0;
else M = 32;
if (!BO{2}) CTR = CTR - 1;
ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != (BO{3}));
cond_ok = BO{0} || ((CR{BI}) == (BO{1}));
if (ctr_ok && cond_ok)
if (AA) NIA = IEA(EXTS(BD_0b00));
else NIA = IEA(CIA + EXTS(BD_0b00));
if (LK) LR = (spreg)IEA(CIA + 4);
0.19,6.BO,11.BI,16./,21.16,31.LK:XL:t::Branch Conditional to Link Register
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
*603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
*603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1995-11-01 19:32:38 +00:00
int M, ctr_ok, cond_ok;
if (is_64bit_implementation && is_64bit_mode) M = 0;
else M = 32;
if (!BO{2}) CTR = CTR - 1;
ctr_ok = BO{2} || ((MASKED(CTR, M, 63) != 0) != BO{3});
cond_ok = BO{0} || (CR{BI} == BO{1});
if (ctr_ok && cond_ok) NIA = IEA(LR_0b00);
if (LK) LR = (spreg)IEA(CIA + 4);
0.19,6.BO,11.BI,16./,21.528,31.LK:XL:t::Branch Conditional to Count Register
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
*603: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
*603e:PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1995-11-01 19:32:38 +00:00
int cond_ok;
cond_ok = BO{0} || (CR{BI} == BO{1});
if (cond_ok) NIA = IEA(CTR_0b00);
if (LK) LR = (spreg)IEA(CIA + 4);
#
# I.2.4.2 System Call Instruction
#
0.17,6./,11./,16./,30.1,31./:SC:t::System Call
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, PPC_SERIALIZE
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, PPC_SERIALIZE
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, PPC_SERIALIZE
1995-11-01 19:32:38 +00:00
system_call_interrupt(processor, cia);
#
# I.2.4.3 Condition Register Logical Instructions
#
0.19,6.BT,11.BA,16.BB,21.257,31./:XL::crand:Condition Register AND
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1995-11-01 19:32:38 +00:00
BLIT32(CR, BT, CR{BA} && CR{BB});
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.19,6.BT,11.BA,16.BB,21.449,31./:XL::cror:Condition Register OR
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1995-11-01 19:32:38 +00:00
BLIT32(CR, BT, CR{BA} || CR{BB});
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.19,6.BT,11.BA,16.BB,21.193,31./:XL::crxor:Condition Register XOR
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1995-11-01 19:32:38 +00:00
BLIT32(CR, BT, CR{BA} != CR{BB});
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.19,6.BT,11.BA,16.BB,21.225,31./:XL::crnand:Condition Register NAND
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1995-11-01 19:32:38 +00:00
BLIT32(CR, BT, !(CR{BA} && CR{BB}));
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.19,6.BT,11.BA,16.BB,21.33,31./:XL::crnor:Condition Register NOR
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1995-11-01 19:32:38 +00:00
BLIT32(CR, BT, !(CR{BA} || CR{BB}));
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.19,6.BT,11.BA,16.BB,21.289,31./:XL::creqv:Condition Register Equivalent
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1995-11-01 19:32:38 +00:00
BLIT32(CR, BT, CR{BA} == CR{BB});
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.19,6.BT,11.BA,16.BB,21.129,31./:XL::crandc:Condition Register AND with Complement
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1995-11-01 19:32:38 +00:00
BLIT32(CR, BT, CR{BA} && !CR{BB});
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.19,6.BT,11.BA,16.BB,21.417,31./:XL::crorc:Condition Register OR with Complement
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1995-11-01 19:32:38 +00:00
BLIT32(CR, BT, CR{BA} || !CR{BB});
#
# I.2.4.4 Condition Register Field Instruction
#
0.19,6.BF,9./,11.BFA,14./,16./,21.0,31./:XL:::Move Condition Register Field
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
1995-11-01 19:32:38 +00:00
MBLIT32(CR, 4*BF, 4*BF+3, EXTRACTED32(CR, 4*BFA, 4*BFA+3));
#
# I.3.3.2 Fixed-Point Load Instructions
#
0.34,6.RT,11.RA,16.D:D:::Load Byte and Zero
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1995-11-01 19:32:38 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + EXTS(D);
*rT = MEM(unsigned, EA, 1);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.87,31./:X:::Load Byte and Zero Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1995-11-01 19:32:38 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + *rB;
*rT = MEM(unsigned, EA, 1);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.35,6.RT,11.RA,16.D:D:::Load Byte and Zero with Update
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1995-11-01 19:32:38 +00:00
unsigned_word EA;
if (RA == 0 || RA == RT)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + EXTS(D);
*rT = MEM(unsigned, EA, 1);
*rA = EA;
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.119,31./:X:::Load Byte and Zero with Update Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1995-11-01 19:32:38 +00:00
unsigned_word EA;
if (RA == 0 || RA == RT)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + *rB;
*rT = MEM(unsigned, EA, 1);
*rA = EA;
0.40,6.RT,11.RA,16.D:D:::Load Halfword and Zero
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1995-11-01 19:32:38 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + EXTS(D);
*rT = MEM(unsigned, EA, 2);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.279,31./:X:::Load Halfword and Zero Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1995-11-01 19:32:38 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + *rB;
*rT = MEM(unsigned, EA, 2);
0.41,6.RT,11.RA,16.D:D:::Load Halfword and Zero with Update
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1995-11-01 19:32:38 +00:00
unsigned_word EA;
if (RA == 0 || RA == RT)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + EXTS(D);
*rT = MEM(unsigned, EA, 2);
*rA = EA;
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.311,31./:X:::Load Halfword and Zero with Update Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1995-11-01 19:32:38 +00:00
unsigned_word EA;
if (RA == 0 || RA == RT)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + *rB;
*rT = MEM(unsigned, EA, 2);
*rA = EA;
0.42,6.RT,11.RA,16.D:D:::Load Halfword Algebraic
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1995-11-01 19:32:38 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + EXTS(D);
*rT = MEM(signed, EA, 2);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.343,31./:X:::Load Halfword Algebraic Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1995-11-01 19:32:38 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + *rB;
*rT = MEM(signed, EA, 2);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.43,6.RT,11.RA,16.D:D:::Load Halfword Algebraic with Update
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1995-11-01 19:32:38 +00:00
unsigned_word EA;
if (RA == 0 || RA == RT)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + EXTS(D);
*rT = MEM(signed, EA, 2);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.375,31./:X:::Load Halfword Algebraic with Update Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1995-11-01 19:32:38 +00:00
unsigned_word EA;
if (RA == 0 || RA == RT)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + *rB;
*rT = MEM(signed, EA, 2);
*rA = EA;
0.32,6.RT,11.RA,16.D:D:::Load Word and Zero
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1995-11-01 19:32:38 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + EXTS(D);
*rT = MEM(unsigned, EA, 4);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.23,31./:X:::Load Word and Zero Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1995-11-01 19:32:38 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + *rB;
*rT = MEM(unsigned, EA, 4);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.33,6.RT,11.RA,16.D:D:::Load Word and Zero with Update
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1995-11-01 19:32:38 +00:00
unsigned_word EA;
if (RA == 0 || RA == RT)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + EXTS(D);
*rT = MEM(unsigned, EA, 4);
*rA = EA;
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.55,31./:X:::Load Word and Zero with Update Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 2, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
1995-11-01 19:32:38 +00:00
unsigned_word EA;
if (RA == 0 || RA == RT)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + *rB;
*rT = MEM(unsigned, EA, 4);
*rA = EA;
0.58,6.RT,11.RA,16.DS,30.2:DS:64::Load Word Algebraic
# unsigned_word b;
# unsigned_word EA;
# if (RA == 0) b = 0;
# else b = *rA;
# EA = b + EXTS(DS_0b00);
# *rT = MEM(signed, EA, 4);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.341,31./:X:64::Load Word Algebraic Indexed
# unsigned_word b;
# unsigned_word EA;
# if (RA == 0) b = 0;
# else b = *rA;
# EA = b + *rB;;
# *rT = MEM(signed, EA, 4);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.373,31./:X:64::Load Word Algebraic with Update Indexed
# unsigned_word EA;
# if (RA == 0 || RA == RT)
# program_interrupt(processor, cia
# illegal_instruction_program_interrupt);
# EA = *rA + *rB;
# *rT = MEM(signed, EA, 4);
# *rA = EA;
0.58,6.RT,11.RA,16.DS,30.0:DS:64::Load Doubleword
# unsigned_word b;
# unsigned_word EA;
# if (RA == 0) b = 0;
# else b = *rA;
# EA = b + EXTS(DS_0b00);
# *rT = MEM(unsigned, EA, 8);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.21,31./:X:64::Load Doubleword Indexed
# unsigned_word b;
# unsigned_word EA;
# if (RA == 0) b = 0;
# else b = *rA;
# EA = b + *rB;
# *rT = MEM(unsigned, EA, 8);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.58,6.RT,11.RA,16.DS,30.1:DS:64::Load Doubleword with Update
# unsigned_word EA;
# if (RA == 0 || RA == RT)
# program_interrupt(processor, cia
# illegal_instruction_program_interrupt);
# EA = *rA + EXTS(DS_0b00);
# *rT = MEM(unsigned, EA, 8);
# *rA = EA;
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.53,31./:DS:64::Load Doubleword with Update Indexed
# unsigned_word EA;
# if (RA == 0 || RA == RT)
# program_interrupt(processor, cia
# illegal_instruction_program_interrupt);
# EA = *rA + *rB;
# *rT = MEM(unsigned, EA, 8);
# *rA = EA;
#
# I.3.3.3 Fixed-Point Store Instructions
#
0.38,6.RS,11.RA,16.D:D:::Store Byte
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + EXTS(D);
STORE(EA, 1, *rS);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16.RB,21.215,31./:X:::Store Byte Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + *rB;
STORE(EA, 1, *rS);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.39,6.RS,11.RA,16.D:D:::Store Byte with Update
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word EA;
if (RA == 0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + EXTS(D);
STORE(EA, 1, *rS);
*rA = EA;
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16.RB,21.247,31./:X:::Store Byte with Update Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word EA;
if (RA == 0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + *rB;
STORE(EA, 1, *rS);
*rA = EA;
0.44,6.RS,11.RA,16.D:D:::Store Half Word
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + EXTS(D);
STORE(EA, 2, *rS);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16.RB,21.407,31./:X:::Store Half Word Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + *rB;
STORE(EA, 2, *rS);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.45,6.RS,11.RA,16.D:D:::Store Half Word with Update
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word EA;
if (RA == 0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + EXTS(D);
STORE(EA, 2, *rS);
*rA = EA;
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16.RB,21.439,31./:X:::Store Half Word with Update Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word EA;
if (RA == 0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + *rB;
STORE(EA, 2, *rS);
*rA = EA;
0.36,6.RS,11.RA,16.D:D:::Store Word
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + EXTS(D);
STORE(EA, 4, *rS);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16.RB,21.151,31./:X:::Store Word Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + *rB;
STORE(EA, 4, *rS);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.37,6.RS,11.RA,16.D:D:::Store Word with Update
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word EA;
if (RA == 0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + EXTS(D);
STORE(EA, 4, *rS);
*rA = EA;
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16.RB,21.183,31./:X:::Store Word with Update Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word EA;
if (RA == 0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + *rB;
STORE(EA, 4, *rS);
*rA = EA;
0.62,6.RS,11.RA,16.DS,30.0:DS:64::Store Doubleword
# unsigned_word b;
# unsigned_word EA;
# if (RA == 0) b = 0;
# else b = *rA;
# EA = b + EXTS(DS_0b00);
# STORE(EA, 8, *rS);
0.31,6.RS,11.RA,16.RB,21.149,31./:X:64::Store Doubleword Indexed
# unsigned_word b;
# unsigned_word EA;
# if (RA == 0) b = 0;
# else b = *rA;
# EA = b + *rB;
# STORE(EA, 8, *rS);
0.62,6.RS,11.RA,16.DS,30.1:DS:64::Store Doubleword with Update
# unsigned_word EA;
# if (RA == 0)
# program_interrupt(processor, cia
# illegal_instruction_program_interrupt);
# EA = *rA + EXTS(DS_0b00);
# STORE(EA, 8, *rS);
# *rA = EA;
0.31,6.RS,11.RA,16.RB,21.181,31./:X:64::Store Doubleword with Update Indexed
# unsigned_word EA;
# if (RA == 0)
# program_interrupt(processor, cia
# illegal_instruction_program_interrupt);
# EA = *rA + *rB;
# STORE(EA, 8, *rS);
# *rA = EA;
#
# I.3.3.4 Fixed-Point Load and Store with Byte Reversal Instructions
#
0.31,6.RT,11.RA,16.RB,21.790,31./:X:::Load Halfword Byte-Reverse Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-08 18:57:06 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + *rB;
*rT = SWAP_2(MEM(unsigned, EA, 2));
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.534,31./:X:::Load Word Byte-Reverse Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-08 18:57:06 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + *rB;
*rT = SWAP_4(MEM(unsigned, EA, 4));
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16.RB,21.918,31./:X:::Store Half Word Byte-Reversed Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-08 18:57:06 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + *rB;
STORE(EA, 2, SWAP_2(*rS));
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16.RB,21.662,31./:X:::Store Word Byte-Reversed Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-08 18:57:06 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + *rB;
STORE(EA, 4, SWAP_4(*rS));
1995-11-01 19:32:38 +00:00
#
# I.3.3.5 Fixed-Point Load and Store Multiple Instrctions
#
0.46,6.RT,11.RA,16.D:D:be::Load Multiple Word
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.47,6.RS,11.RA,16.D:D:be::Store Multiple Word
#
# I.3.3.6 Fixed-Point Move Assist Instructions
#
0.31,6.RT,11.RA,16.NB,21.597,31./:X:be::Load String Word Immediate
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.533,31./:X:be::Load String Word Indexed
0.31,6.RS,11.RA,16.NB,21.725,31./:X:be::Store String Word Immedate
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16.RB,21.661,31./:X:be::Store String Word Indexed
#
# I.3.3.7 Storage Synchronization Instructions
#
# HACK: Rather than monitor addresses looking for a reason
# to cancel a reservation. This code instead keeps
# a copy of the data read from memory. Before performing
# a store, the memory area is checked to see if it has
# been changed.
0.31,6.RT,11.RA,16.RB,21.20,31./:X:::Load Word And Reserve Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
*603: PPC_UNIT_LSU, PPC_UNIT_IU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_IU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, PPC_SERIALIZE
1995-11-01 19:32:38 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + *rB;
RESERVE = 1;
RESERVE_ADDR = real_addr(EA, 1/*is-read?*/);
RESERVE_DATA = MEM(unsigned, EA, 4);
*rT = RESERVE_DATA;
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.84,31./:X:64::Load Doubleword And Reserve Indexed
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + *rB;
RESERVE = 1;
RESERVE_ADDR = real_addr(EA, 1/*is-read?*/);
RESERVE_DATA = MEM(unsigned, EA, 8);
*rT = RESERVE_DATA;
0.31,6.RS,11.RA,16.RB,21.150,31.1:X:::Store Word Conditional Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 8, 8, 0
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 8, 8, 0
*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + *rB;
if (RESERVE) {
if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/)
&& /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 4)) {
STORE(EA, 4, *rS);
CR_SET_XER_SO(0, cr_i_zero);
}
else {
/* ment to randomly to store, we never do! */
CR_SET_XER_SO(0, 0);
}
RESERVE = 0;
}
else {
CR_SET_XER_SO(0, 0);
}
0.31,6.RS,11.RA,16.RB,21.214,31.1:X:64::Store Doubleword Conditional Indexed
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + *rB;
if (RESERVE) {
if (RESERVE_ADDR == real_addr(EA, 0/*is-read?*/)
&& /*HACK*/ RESERVE_DATA == MEM(unsigned, EA, 8)) {
STORE(EA, 8, *rS);
CR_SET_XER_SO(0, cr_i_zero);
}
else {
/* ment to randomly to store, we never do */
CR_SET_XER_SO(0, 0);
}
RESERVE = 0;
}
else {
CR_SET_XER_SO(0, 0);
}
0.31,6./,11./,16./,21.598,31./:X::sync:Synchronize
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, PPC_SERIALIZE
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, PPC_SERIALIZE
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
1995-11-01 19:32:38 +00:00
/* do nothing */
#
# I.3.3.9 Fixed-Point Arithmetic Instructions
#
0.14,6.RT,11.RA,16.SI:D:T::Add Immediate
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
if (RA_is_0) *rT = EXTS(SI);
else *rT = *rA + EXTS(SI);
1995-11-15 22:53:59 +00:00
1995-11-01 19:32:38 +00:00
0.15,6.RT,11.RA,16.SI:D:::Add Immediate Shifted
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
if (RA_is_0) *rT = EXTS(SI) << 16;
else *rT = *rA + (EXTS(SI) << 16);
1995-11-15 22:53:59 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.OE,22.266,31.Rc:XO:::Add
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
ALU_BEGIN(*rA);
ALU_ADD(*rB);
ALU_END(*rT, 0/*CA*/, OE, Rc);
1995-11-15 22:53:59 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.OE,22.40,31.Rc:XO:::Subtract From
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
ALU_BEGIN(*rA);
ALU_NOT;
ALU_ADD(*rB);
ALU_ADD(1);
ALU_END(*rT, 0/*CA*/, OE, Rc);
1995-11-15 22:53:59 +00:00
1995-11-01 19:32:38 +00:00
0.12,6.RT,11.RA,16.SI:D:::Add Immediate Carrying
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
ALU_BEGIN(*rA);
ALU_ADD(EXTS(SI));
ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
1995-11-15 22:53:59 +00:00
1995-11-01 19:32:38 +00:00
0.13,6.RT,11.RA,16.SI:D:::Add Immediate Carrying and Record
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
ALU_BEGIN(*rA);
ALU_ADD(EXTS(SI));
ALU_END(*rT, 1/*CA*/, 0/*OE*/, 1/*Rc*/);
1995-11-15 22:53:59 +00:00
1995-11-01 19:32:38 +00:00
0.8,6.RT,11.RA,16.SI:D:::Subtract From Immediate Carrying
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
ALU_BEGIN(*rA);
ALU_NOT;
ALU_ADD(EXTS(SI));
ALU_ADD(1);
ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
1995-11-15 22:53:59 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.OE,22.10,31.Rc:XO:::Add Carrying
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
ALU_BEGIN(*rA);
ALU_ADD(*rB);
ALU_END(*rT, 1/*CA*/, OE, Rc);
1995-11-15 22:53:59 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.OE,22.8,31.Rc:XO:::Subtract From Carrying
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
/* RT <- ~RA + RB + 1 === RT <- RB - RA */
ALU_BEGIN(*rA);
ALU_NOT;
ALU_ADD(*rB);
ALU_ADD(1);
ALU_END(*rT, 1/*CA*/, OE, Rc);
1995-11-15 22:53:59 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.OE,22.138,31.Rc:XO:::Add Extended
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
ALU_BEGIN(*rA);
ALU_ADD(*rB);
ALU_ADD_CA;
ALU_END(*rT, 1/*CA*/, OE, Rc);
1995-11-15 22:53:59 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.OE,22.136,31.Rc:XO:::Subtract From Extended
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
ALU_BEGIN(*rA);
ALU_NOT;
ALU_ADD(*rB);
ALU_ADD_CA;
ALU_END(*rT, 1/*CA*/, OE, Rc);
1995-11-15 22:53:59 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16./,21.OE,22.234,31.Rc:XO:::Add to Minus One Extended
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
# ALU_BEGIN(*rA);
# ALU_ADD_CA;
# ALU_SUB(1);
# ALU_END(*rT, 1/*CA*/, OE, Rc);
1995-11-15 22:53:59 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16./,21.OE,22.232,31.Rc:XO:::Subtract From Minus One Extended
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
# ALU_BEGIN(*rA);
# ALU_NOT;
# ALU_ADD_CA;
# ALU_SUB(1);
# ALU_END(*rT, 1/*CA*/, OE, Rc);
1995-11-15 22:53:59 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16./,21.OE,22.202,31.Rc:XO::addze:Add to Zero Extended
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
ALU_BEGIN(*rA);
ALU_ADD_CA;
ALU_END(*rT, 1/*CA*/, OE, Rc);
1995-11-15 22:53:59 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16./,21.OE,22.200,31.Rc:XO:::Subtract from Zero Extended
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
ALU_BEGIN(*rA);
ALU_NOT;
ALU_ADD_CA;
ALU_END(*rT, 1/*CA*/, OE, Rc);
1995-11-15 22:53:59 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16./,21.OE,22.104,31.Rc:XO:::Negate
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
ALU_BEGIN(*rA);
ALU_NOT;
ALU_ADD(1);
ALU_END(*rT,0/*CA*/,OE,Rc);
1995-11-15 22:53:59 +00:00
1995-11-01 19:32:38 +00:00
0.7,6.RT,11.RA,16.SI:D::mulli:Multiply Low Immediate
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
1995-11-01 19:32:38 +00:00
signed_word prod = *rA * EXTS(SI);
*rT = prod;
1995-11-15 22:53:59 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.OE,22.233,31.Rc:D:64::Multiply Low Doubleword
1995-11-15 22:53:59 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.OE,22.235,31.Rc:XO::mullw:Multiply Low Word
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0
1995-11-01 19:32:38 +00:00
signed64 a = (signed32)(*rA);
signed64 b = (signed32)(*rB);
signed64 prod = a * b;
signed_word t = prod;
*rT = *rA * *rB;
if (t != prod && OE)
XER |= (xer_overflow | xer_summary_overflow);
CR0_COMPARE(t, 0, Rc);
1995-11-15 22:53:59 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21./,22.73,31.Rc:XO:64::Multiply High Doubleword
1995-11-15 22:53:59 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21./,22.75,31.Rc:XO::mulhw:Multiply High Word
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 5, 5, 0
*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0
1995-11-01 19:32:38 +00:00
signed64 a = (signed32)(*rA);
signed64 b = (signed32)(*rB);
signed64 prod = a * b;
signed_word t = EXTRACTED64(prod, 0, 31);
*rT = t;
CR0_COMPARE(t, 0, Rc);
1995-11-15 22:53:59 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21./,22.9,31.Rc:XO:64::Multiply High Doubleword Unsigned
1995-11-15 22:53:59 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21./,22.11,31.Rc:XO::milhwu:Multiply High Word Unsigned
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 10, 10, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 6, 6, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 6, 6, 0
*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 4, 4, 0
1995-11-01 19:32:38 +00:00
unsigned64 a = (unsigned32)(*rA);
unsigned64 b = (unsigned32)(*rB);
unsigned64 prod = a * b;
signed_word t = EXTRACTED64(prod, 0, 31);
*rT = t;
CR0_COMPARE(t, 0, Rc);
1995-11-15 22:53:59 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.OE,22.489,31.Rc:XO:64::Divide Doubleword
1995-11-15 22:53:59 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.OE,22.491,31.Rc:XO::divw:Divide Word
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 36, 36, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 20, 20, 0
1995-11-01 19:32:38 +00:00
signed64 dividend = (signed32)(*rA);
signed64 divisor = (signed32)(*rB);
if (divisor == 0 /* nb 0x8000..0 is sign extended */
|| (dividend == 0x80000000 && divisor == -1)) {
if (OE)
XER |= (xer_overflow | xer_summary_overflow);
CR0_COMPARE(0, 0, Rc);
}
else {
signed64 quotent = dividend / divisor;
*rT = quotent;
CR0_COMPARE((signed_word)quotent, 0, Rc);
}
0.31,6.RT,11.RA,16.RB,21.OE,22.457,31.Rc:XO:64::Divide Doubleword Unsigned
1995-11-15 22:53:59 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11.RA,16.RB,21.OE,22.459,31.Rc:XO::divwu:Divide Word Unsigned
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 36, 36, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 37, 37, 0
*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 20, 20, 0
1995-11-01 19:32:38 +00:00
unsigned64 dividend = (unsigned32)(*rA);
unsigned64 divisor = (unsigned32)(*rB);
if (divisor == 0) {
if (OE)
XER |= (xer_overflow | xer_summary_overflow);
CR0_COMPARE(0, 0, Rc);
}
else {
unsigned64 quotent = dividend / divisor;
*rT = quotent;
CR0_COMPARE((signed_word)quotent, 0, Rc);
}
#
# I.3.3.10 Fixed-Point Compare Instructions
#
0.11,6.BF,9./,10.L,11.RA,16.SI:D:::Compare Immediate
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
if (!is_64bit_mode && L)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
else {
signed_word a;
signed_word b = EXTS(SI);
if (L == 0)
a = EXTENDED(*rA);
else
a = *rA;
CR_COMPARE(BF, a, b);
}
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.BF,9./,10.L,11.RA,16.RB,21.0,31./:X:::Compare
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
if (!is_64bit_mode && L)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
else {
signed_word a;
signed_word b;
if (L == 0) {
a = EXTENDED(*rA);
b = EXTENDED(*rB);
}
else {
a = *rA;
b = *rB;
}
CR_COMPARE(BF, a, b);
}
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.10,6.BF,9./,10.L,11.RA,16.UI:D:::Compare Logical Immediate
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
if (!is_64bit_mode && L)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
else {
unsigned_word a;
unsigned_word b = UI;
if (L == 0)
a = MASKED(*rA, 32, 63);
else
a = *rA;
CR_COMPARE(BF, a, b);
}
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.BF,9./,10.L,11.RA,16.RB,21.32,31./:X:::Compare Logical
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
if (!is_64bit_mode && L)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
else {
unsigned_word a;
unsigned_word b;
if (L == 0) {
a = MASKED(*rA, 32, 63);
b = MASKED(*rB, 32, 63);
}
else {
a = *rA;
b = *rB;
}
CR_COMPARE(BF, a, b);
}
#
# I.3.3.11 Fixed-Point Trap Instructions
#
0.2,6.TO,11.RA,16.SI:D:64::Trap Doubleword Immediate
if (!is_64bit_mode)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
else {
signed_word a = *rA;
signed_word b = EXTS(SI);
if ((a < b && TO{0})
|| (a > b && TO{1})
|| (a == b && TO{2})
|| ((unsigned_word)a < (unsigned_word)b && TO{3})
|| ((unsigned_word)a > (unsigned_word)b && TO{4})
)
program_interrupt(processor, cia,
trap_program_interrupt);
}
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.3,6.TO,11.RA,16.SI:D:::Trap Word Immediate
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
signed_word a = EXTENDED(*rA);
signed_word b = EXTS(SI);
if ((a < b && TO{0})
|| (a > b && TO{1})
|| (a == b && TO{2})
|| ((unsigned_word)a < (unsigned_word)b && TO{3})
|| ((unsigned_word)a > (unsigned_word)b && TO{4})
)
program_interrupt(processor, cia,
trap_program_interrupt);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.TO,11.RA,16.RB,21.68,31./:X:64::Trap Doubleword
if (!is_64bit_mode)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
else {
signed_word a = *rA;
signed_word b = *rB;
if ((a < b && TO{0})
|| (a > b && TO{1})
|| (a == b && TO{2})
|| ((unsigned_word)a < (unsigned_word)b && TO{3})
|| ((unsigned_word)a > (unsigned_word)b && TO{4})
)
program_interrupt(processor, cia,
trap_program_interrupt);
}
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.TO,11.RA,16.RB,21.4,31./:X:::Trap Word
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
signed_word a = EXTENDED(*rA);
signed_word b = EXTENDED(*rB);
if (TO == 12 && rA == rB) {
ITRACE(trace_breakpoint, ("breakpoint\n"));
cpu_halt(processor, cia, was_trap, 0);
}
else if ((a < b && TO{0})
|| (a > b && TO{1})
|| (a == b && TO{2})
|| ((unsigned_word)a < (unsigned_word)b && TO{3})
|| ((unsigned_word)a > (unsigned_word)b && TO{4})
)
program_interrupt(processor, cia,
trap_program_interrupt);
#
# I.3.3.12 Fixed-Point Logical Instructions
#
0.28,6.RS,11.RA,16.UI:D:::AND Immediate
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
*rA = *rS & UI;
CR0_COMPARE(*rA, 0, 1/*Rc*/);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.29,6.RS,11.RA,16.UI:D:::AND Immediate Shifted
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
*rA = *rS & (UI << 16);
CR0_COMPARE(*rA, 0, 1/*Rc*/);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.24,6.RS,11.RA,16.UI:D:::OR Immediate
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
*rA = *rS | UI;
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.25,6.RS,11.RA,16.UI:D:::OR Immediate Shifted
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
*rA = *rS | (UI << 16);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.26,6.RS,11.RA,16.UI:D:::XOR Immediate
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
*rA = *rS ^ UI;
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.27,6.RS,11.RA,16.UI:D:::XOR Immediate Shifted
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
*rA = *rS ^ (UI << 16);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16.RB,21.28,31.Rc:X:::AND
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
*rA = *rS & *rB;
CR0_COMPARE(*rA, 0, Rc);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16.RB,21.444,31.Rc:X:::OR
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
*rA = *rS | *rB;
CR0_COMPARE(*rA, 0, Rc);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16.RB,21.316,31.Rc:X:::XOR
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
*rA = *rS ^ *rB;
CR0_COMPARE(*rA, 0, Rc);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16.RB,21.476,31.Rc:X:::NAND
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
*rA = ~(*rS & *rB);
CR0_COMPARE(*rA, 0, Rc);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16.RB,21.124,31.Rc:X:::NOR
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
*rA = ~(*rS | *rB);
CR0_COMPARE(*rA, 0, Rc);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16.RB,21.284,31.Rc:X:::Equivalent
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
# *rA = ~(*rS ^ *rB); /* A === B */
# CR0_COMPARE(*rA, 0, Rc);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16.RB,21.60,31.Rc:X:::AND with Complement
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
*rA = *rS & ~*rB;
CR0_COMPARE(*rA, 0, Rc);
0.31,6.RS,11.RA,16.RB,21.412,31.Rc:X:::OR with Complement
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
*rA = *rS | ~*rB;
CR0_COMPARE(*rA, 0, Rc);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16./,21.954,31.Rc:X::extsb:Extend Sign Byte
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
*rA = (signed_word)(signed8)*rS;
CR0_COMPARE(*rA, 0, Rc);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16./,21.922,31.Rc:X::extsh:Extend Sign Half Word
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
*rA = (signed_word)(signed16)*rS;
CR0_COMPARE(*rA, 0, Rc);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16./,21.986,31.Rc:X:64::Extend Sign Word
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
# *rA = (signed_word)(signed32)*rS;
# CR0_COMPARE(*rA, 0, Rc);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16./,21.58,31.Rc:X:64::Count Leading Zeros Doubleword
# int count = 0;
# unsigned64 mask = BIT64(0);
# unsigned64 source = *rS;
# while (!(source & mask) && mask != 0) {
# mask >>= 1;
# count++;
# }
# *rA = count;
# CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16./,21.26,31.Rc:X:::Count Leading Zeros Word
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
int count = 0;
unsigned32 mask = BIT32(0);
unsigned32 source = *rS;
while (!(source & mask) && mask != 0) {
mask >>= 1;
count++;
}
*rA = count;
CR0_COMPARE(count, 0, Rc); /* FIXME - is this correct */
#
# I.3.3.13 Fixed-Point Rotate and Shift Instructions
#
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
# long n = (sh_5 << 4) | sh_0_4;
# unsigned_word r = ROTL64(*rS, n);
# long b = (mb_5 << 4) | mb_0_4;
# unsigned_word m = MASK(b, 63);
# signed_word result = r & m;
# *rA = result;
# CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
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
# long n = (sh_5 << 4) | sh_0_4;
# unsigned_word r = ROTL64(*rS, n);
# long e = (me_5 << 4) | me_0_4;
# unsigned_word m = MASK(0, e);
# signed_word result = r & m;
# *rA = result;
# CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
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
# long n = (sh_5 << 4) | sh_0_4;
# unsigned_word r = ROTL64(*rS, n);
# long b = (mb_5 << 4) | mb_0_4;
# unsigned_word m = MASK(0, (64-n));
# signed_word result = r & m;
# *rA = result;
# CR0_COMPARE(result, 0, Rc); /* FIXME - is this correct */
0.21,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M:::Rotate Left Word Immediate then AND with Mask
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
long n = SH;
unsigned32 s = *rS;
unsigned32 r = ROTL32(s, n);
unsigned32 m = MASK(MB+32, ME+32);
signed_word result = r & m;
*rA = result;
CR0_COMPARE(result, 0, Rc);
ITRACE(trace_alu,
("n=%d, s=0x%x, r=0x%x, m=0x%x, result=0x%x, cr=0x%x\n",
n, s, r, m, result, CR));
0.30,6.RS,11.RA,16.RB,21.mb,27.8,31.Rc:MDS:64::Rotate Left Doubleword then Clear Left
# long n = MASKED(*rB, 58, 63);
# unsigned_word r = ROTL64(*rS, n);
# long b = (mb_5 << 4) | mb_0_4;
# unsigned_word m = MASK(b, 63);
# signed_word result = r & m;
# *rA = result;
# CR0_COMPARE(result, 0, Rc);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.30,6.RS,11.RA,16.RB,21.me,27.9,31.Rc:MDS:64::Rotate Left Doubleword then Clear Right
# long n = MASKED(*rB, 58, 63);
# unsigned_word r = ROTL64(*rS, n);
# long e = (me_5 << 4) | me_0_4;
# unsigned_word m = MASK(0, e);
# signed_word result = r & m;
# *rA = result;
# CR0_COMPARE(result, 0, Rc);
0.23,6.RS,11.RA,16.RB,21.MB,26.ME,31.Rc:M:::Rotate Left Word then AND with Mask
# long n = MASKED(*rB, 59, 63);
# unsigned32 r = ROTL32(*rS, n);
# unsigned32 m = MASK(MB+32, ME+32);
# signed_word result = r & m;
# *rA = result;
# CR0_COMPARE(result, 0, Rc);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
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
# long n = (sh_5 << 4) | sh_0_4;
# unsigned_word r = ROTL64(*rS, n);
# long b = (mb_5 << 4) | mb_0_4;
# unsigned_word m = MASK(b, (64-n));
# signed_word result = (r & m) | (*rA & ~m)
# *rA = result;
# CR0_COMPARE(result, 0, Rc);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.20,6.RS,11.RA,16.SH,21.MB,26.ME,31.Rc:M::rlwimi:Rotate Left Word Immediate then Mask Insert
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
long n = SH;
unsigned32 r = ROTL32(*rS, n);
unsigned32 m = MASK(MB+32, ME+32);
signed_word result = (r & m) | (*rA & ~m);
*rA = result;
ITRACE(trace_alu, (": n=%d *rS=0x%x r=0x%x m=0x%x result=0x%x\n",
n, *rS, r, m, result));
CR0_COMPARE(result, 0, Rc);
0.31,6.RS,11.RA,16.RB,21.27,31.Rc:X:64::Shift Left Doubleword
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16.RB,21.24,31.Rc:X:::Shift Left Word
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
int n = MASKED(*rB, 59, 63);
unsigned32 source = *rS;
signed_word shifted;
if (n < 32)
shifted = (source << n);
else
shifted = 0;
*rA = shifted;
CR0_COMPARE(shifted, 0, Rc);
ITRACE(trace_alu,
("n=%d, source=0x%x, shifted=0x%x\n",
n, source, shifted));
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16.RB,21.539,31.Rc:X:64::Shift Right Doubleword
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16.RB,21.536,31.Rc:X:::Shift Right Word
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
int n = MASKED(*rB, 59, 63);
unsigned32 source = *rS;
signed_word shifted;
if (n < 32)
shifted = (source >> n);
else
shifted = 0;
*rA = shifted;
CR0_COMPARE(shifted, 0, Rc);
ITRACE(trace_alu, \
("n=%d, source=0x%x, shifted=0x%x\n",
n, source, shifted));
0.31,6.RS,11.RA,16.sh_0_4,21.413,30.sh_5,31.Rc:XS:64::Shift Right Algebraic Doubleword Immediate
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16.SH,21.824,31.Rc:X:::Shift Right Algebraic Word Immediate
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
int n = SH;
signed_word r = ROTL32(*rS, /*64*/32-n);
signed_word m = MASK(n+32, 63);
int S = MASKED(*rS, 32, 32);
signed_word shifted = (r & m) | (S ? ~m : 0);
*rA = shifted;
if (S && ((r & ~m) & MASK(32, 63)) != 0)
XER |= xer_carry;
else
XER &= ~xer_carry;
CR0_COMPARE(shifted, 0, Rc);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16.RB,21.794,31.Rc:X:64::Shift Right Algebraic Doubleword
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16.RB,21.792,31.Rc:X:::Shift Right Algebraic Word
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603e:PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
1995-11-01 19:32:38 +00:00
int n = MASKED(*rB, 58, 63);
int shift = (n >= 31 ? 31 : n);
signed32 source = (signed32)*rS; /* signed to keep sign bit */
signed32 shifted = source >> shift;
unsigned32 mask = ((unsigned32)-1) >> (31-shift);
*rA = (signed_word)shifted; /* if 64bit will sign extend */
if (source < 0 && (source & mask))
XER |= xer_carry;
else
XER &= ~xer_carry;
CR0_COMPARE(shifted, 0, Rc);
#
# I.3.3.14 Move to/from System Register Instructions
#
1995-11-15 22:53:59 +00:00
0.31,6.RS,11.spr,21.467,31./:XFX::mtspr %SPR, %RS:Move to Special Purpose Register
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, 0
*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
1995-11-01 19:32:38 +00:00
int n = (spr{5:9} << 5) | spr{0:4};
if (spr{0} && IS_PROBLEM_STATE(processor))
program_interrupt(processor, cia,
privileged_instruction_program_interrupt);
else if (!spr_is_valid(n)
|| spr_is_readonly(n))
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
else {
spreg new_val = (spr_length(n) == 64
? *rS
: MASKED(*rS, 32, 63));
/* HACK - time base registers need to be updated immediatly */
if (WITH_TIME_BASE) {
signed64 time_base;
switch (n) {
case spr_tbu:
cpu_set_time_base(processor,
1995-11-15 22:53:59 +00:00
(MASKED64(cpu_get_time_base(processor), 32, 63)
| INSERTED64(new_val, 0, 31)));
1995-11-01 19:32:38 +00:00
break;
case spr_tbl:
cpu_set_time_base(processor,
1995-11-15 22:53:59 +00:00
(MASKED64(cpu_get_time_base(processor), 0, 31)
| INSERTED64(new_val, 32, 63)));
1995-11-01 19:32:38 +00:00
break;
case spr_dec:
cpu_set_decrementer(processor, new_val);
break;
default:
SPREG(n) = new_val;
break;
}
}
else {
SPREG(n) = new_val;
}
}
1995-11-16 19:02:52 +00:00
1995-11-15 22:53:59 +00:00
0.31,6.RT,11.spr,21.339,31./:XFX::mfspr %RT, %SPR:Move from Special Purpose Register
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
1995-11-01 19:32:38 +00:00
int n = (spr{5:9} << 5) | spr{0:4};
if (spr{0} && IS_PROBLEM_STATE(processor))
program_interrupt(processor, cia,
privileged_instruction_program_interrupt);
else if (!spr_is_valid(n))
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
else {
/* HACK - some SPR's need to get their value extracted specially */
*rT = SPREG(n);
}
1995-11-16 19:02:52 +00:00
# FIXME: 604 uses SCIU{1,2} if only one bit is being set
1995-11-01 19:32:38 +00:00
0.31,6.RS,11./,12.FXM,20./,21.144,31./:XFX::mtfcr:Move to Condition Register Fields
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
1995-11-01 19:32:38 +00:00
if (FXM == 0xff) {
CR = *rS;
}
else {
unsigned_word mask = 0;
unsigned_word f;
for (f = 0; f < 8; f++) {
if (FXM & (0x80 >> f))
mask |= (0xf << 4*(7-f));
}
CR = (MASKED(*rS, 32, 63) & mask) | (CR & ~mask);
}
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.BF,9./,11./,16./,21.512,31./:X:::Move to Condition Register from XER
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11./,16./,21.19,31./:X:::Move From Condition Register
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
1995-11-01 19:32:38 +00:00
*rT = (unsigned32)CR;
#
# I.4.6.2 Floating-Point Load Instructions
#
0.48,6.FRT,11.RA,16.D:D:f:lfs:Load Floating-Point Single
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + EXTS(D);
*frT = DOUBLE(MEM(unsigned, EA, 4));
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.FRT,11.RA,16.RB,21.535,31./:X:f::Load Floating-Point Single Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + *rB;
*frT = DOUBLE(MEM(unsigned, EA, 4));
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.49,6.FRT,11.RA,16.D:D:f::Load Floating-Point Single with Update
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word EA;
if (RA == 0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + EXTS(D);
*frT = DOUBLE(MEM(unsigned, EA, 4));
*rA = EA;
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.FRT,11.RA,16.RB,21.576,31./:X:f::Load Floating-Point Single with Update Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word EA;
if (RA == 0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + *rB;
*frT = DOUBLE(MEM(unsigned, EA, 4));
*rA = EA;
0.50,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + EXTS(D);
*frT = MEM(unsigned, EA, 8);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.FRT,11.RA,16.RB,21.599,31./:X:f::Load Floating-Point Double Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + *rB;
*frT = MEM(unsigned, EA, 8);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.51,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double with Update
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word EA;
if (RA == 0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + EXTS(D);
*frT = MEM(unsigned, EA, 8);
*rA = EA;
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.FRT,11.RA,16.RB,21.631,31./:X:f::Load Floating-Point Double with Update Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 3, 3, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word EA;
if (RA == 0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + *rB;
*frT = MEM(unsigned, EA, 8);
*rA = EA;
#
# I.4.6.3 Floating-Point Store Instructions
#
0.52,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + EXTS(D);
STORE(EA, 4, SINGLE(*frS));
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.FRS,11.RA,16.RB,21.663,31./:X:f::Store Floating-Point Single Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + *rB;
STORE(EA, 4, SINGLE(*frS));
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.53,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single with Update
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word EA;
if (RA == 0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + EXTS(D);
STORE(EA, 4, SINGLE(*frS));
*rA = EA;
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.FRS,11.RA,16.RB,21.695,31./:X:f::Store Floating-Point Single with Update Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word EA;
if (RA == 0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + *rB;
STORE(EA, 4, SINGLE(*frS));
*rA = EA;
0.54,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + EXTS(D);
STORE(EA, 8, *frS);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.FRS,11.RA,16.RB,21.727,31./:X:f::Store Floating-Point Double Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + *rB;
STORE(EA, 8, *frS);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.55,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double with Update
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word EA;
if (RA == 0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + EXTS(D);
STORE(EA, 8, *frS);
*rA = EA;
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.FRS,11.RA,16.RB,21.759,31./:X:f::Store Floating-Point Double with Update Indexed
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-01 19:32:38 +00:00
unsigned_word EA;
if (RA == 0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + *rB;
STORE(EA, 8, *frS);
*rA = EA;
#
# I.4.6.4 Floating-Point Move Instructions
#
0.63,6.FRT,11./,16.FRB,21.72,31.Rc:X:f::Floating Move Register
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
1995-11-01 19:32:38 +00:00
*frT = *frB;
CR1_UPDATE(Rc);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.63,6.FRT,11./,16.FRB,21.40,31.Rc:X:f::Floating Negate
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
1995-11-01 19:32:38 +00:00
*frT = *frB ^ BIT64(0);
CR1_UPDATE(Rc);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.63,6.FRT,11./,16.FRB,21.264,31.Rc:X:f::Floating Absolute Value
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
1995-11-01 19:32:38 +00:00
*frT = *frB & ~BIT64(0);
CR1_UPDATE(Rc);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.63,6.FRT,11./,16.FRB,21.136,31.Rc:X:f::Floating Negative Absolute Value
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
1995-11-01 19:32:38 +00:00
*frT = *frB | BIT64(0);
CR1_UPDATE(Rc);
#
# I.4.6.5 Floating-Point Arithmetic Instructions
#
0.63,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadd:Floating Add
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
1995-11-01 19:32:38 +00:00
FPSCR_BEGIN;
if (is_invalid_operation(processor, cia,
*frA, *frB,
fpscr_vxsnan | fpscr_vxisi,
0, /*single?*/
0) /*negate?*/) {
invalid_arithemetic_operation(processor, cia,
frT, *frA, *frB, 0,
0, /*instruction_is_frsp*/
0, /*instruction_is_convert_to_64bit*/
0, /*instruction_is_convert_to_32bit*/
0); /*single-precision*/
}
else {
/*HACK!*/
double s = *(double*)frA + *(double*)frB;
*(double*)frT = s;
}
FPSCR_END(Rc);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.59,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadds:Floating Add Single
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
1995-11-01 19:32:38 +00:00
FPSCR_BEGIN;
if (is_invalid_operation(processor, cia,
*frA, *frB,
fpscr_vxsnan | fpscr_vxisi,
1, /*single?*/
0) /*negate?*/) {
invalid_arithemetic_operation(processor, cia,
frT, *frA, *frB, 0,
0, /*instruction_is_frsp*/
0, /*instruction_is_convert_to_64bit*/
0, /*instruction_is_convert_to_32bit*/
1); /*single-precision*/
}
else {
/*HACK!*/
float s = *(double*)frA + *(double*)frB;
*(double*)frT = s;
}
FPSCR_END(Rc);
0.63,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsub:Floating Subtract
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
1995-11-01 19:32:38 +00:00
FPSCR_BEGIN;
if (is_invalid_operation(processor, cia,
*frA, *frB,
fpscr_vxsnan | fpscr_vxisi,
0, /*single?*/
1) /*negate?*/) {
invalid_arithemetic_operation(processor, cia,
frT, *frA, *frB, 0,
0, /*instruction_is_frsp*/
0, /*instruction_is_convert_to_64bit*/
0, /*instruction_is_convert_to_32bit*/
0); /*single-precision*/
}
else {
/*HACK!*/
double s = *(double*)frA - *(double*)frB;
*(double*)frT = s;
}
FPSCR_END(Rc);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.59,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsubs:Floating Subtract Single
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
1995-11-01 19:32:38 +00:00
FPSCR_BEGIN;
if (is_invalid_operation(processor, cia,
*frA, *frB,
fpscr_vxsnan | fpscr_vxisi,
1, /*single?*/
1) /*negate?*/) {
invalid_arithemetic_operation(processor, cia,
frT, *frA, *frB, 0,
0, /*instruction_is_frsp*/
0, /*instruction_is_convert_to_64bit*/
0, /*instruction_is_convert_to_32bit*/
1); /*single-precision*/
}
else {
/*HACK!*/
float s = *(double*)frA - *(double*)frB;
*(double*)frT = s;
}
FPSCR_END(Rc);
0.63,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmul:Floating Multiply
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
1995-11-01 19:32:38 +00:00
FPSCR_BEGIN;
if (is_invalid_operation(processor, cia,
*frA, *frC,
fpscr_vxsnan | fpscr_vximz,
0, /*single?*/
0) /*negate?*/) {
invalid_arithemetic_operation(processor, cia,
frT, *frA, 0, *frC,
0, /*instruction_is_frsp*/
0, /*instruction_is_convert_to_64bit*/
0, /*instruction_is_convert_to_32bit*/
0); /*single-precision*/
}
else {
/*HACK!*/
double s = *(double*)frA * *(double*)frC;
*(double*)frT = s;
}
FPSCR_END(Rc);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.59,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmuls:Floating Multiply Single
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
1995-11-01 19:32:38 +00:00
FPSCR_BEGIN;
if (is_invalid_operation(processor, cia,
*frA, *frC,
fpscr_vxsnan | fpscr_vximz,
1, /*single?*/
0) /*negate?*/) {
invalid_arithemetic_operation(processor, cia,
frT, *frA, 0, *frC,
0, /*instruction_is_frsp*/
0, /*instruction_is_convert_to_64bit*/
0, /*instruction_is_convert_to_32bit*/
1); /*single-precision*/
}
else {
/*HACK!*/
float s = *(double*)frA * *(double*)frC;
*(double*)frT = s;
}
FPSCR_END(Rc);
0.63,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdiv:Floating Divide
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 31, 31, 0
*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 33, 33, 0
*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 33, 33, 0
*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 32, 32, 0
1995-11-01 19:32:38 +00:00
FPSCR_BEGIN;
if (is_invalid_operation(processor, cia,
*frA, *frB,
fpscr_vxsnan | fpscr_vxzdz,
0, /*single?*/
0) /*negate?*/) {
invalid_arithemetic_operation(processor, cia,
frT, *frA, *frB, 0,
0, /*instruction_is_frsp*/
0, /*instruction_is_convert_to_64bit*/
0, /*instruction_is_convert_to_32bit*/
0); /*single-precision*/
}
else {
/*HACK!*/
double s = *(double*)frA / *(double*)frB;
*(double*)frT = s;
}
FPSCR_END(Rc);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.59,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdivs:Floating Divide Single
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 17, 17, 0
*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0
*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0
*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 18, 18, 0
1995-11-01 19:32:38 +00:00
FPSCR_BEGIN;
if (is_invalid_operation(processor, cia,
*frA, *frB,
fpscr_vxsnan | fpscr_vxzdz,
1, /*single?*/
0) /*negate?*/) {
invalid_arithemetic_operation(processor, cia,
frT, *frA, *frB, 0,
0, /*instruction_is_frsp*/
0, /*instruction_is_convert_to_64bit*/
0, /*instruction_is_convert_to_32bit*/
1); /*single-precision*/
}
else {
/*HACK!*/
float s = *(double*)frA / *(double*)frB;
*(double*)frT = s;
}
FPSCR_END(Rc);
0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f:fmadd:Floating Multiply-Add
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
1995-11-01 19:32:38 +00:00
FPSCR_BEGIN;
double product; /*HACK! - incorrectly loosing precision ... */
/* compute the multiply */
if (is_invalid_operation(processor, cia,
*frA, *frC,
fpscr_vxsnan | fpscr_vximz,
0, /*single?*/
0) /*negate?*/) {
invalid_arithemetic_operation(processor, cia,
(unsigned64*)&product, *frA, 0, *frC,
0, /*instruction_is_frsp*/
0, /*instruction_is_convert_to_64bit*/
0, /*instruction_is_convert_to_32bit*/
0); /*single-precision*/
}
else {
/*HACK!*/
product = *(double*)frA * *(double*)frC;
}
/* compute the add */
if (is_invalid_operation(processor, cia,
product, *frB,
fpscr_vxsnan | fpscr_vxisi,
0, /*single?*/
0) /*negate?*/) {
invalid_arithemetic_operation(processor, cia,
frT, product, *frB, 0,
0, /*instruction_is_frsp*/
0, /*instruction_is_convert_to_64bit*/
0, /*instruction_is_convert_to_32bit*/
0); /*single-precision*/
}
else {
/*HACK!*/
double s = product + *(double*)frB;
*(double*)frT = s;
}
FPSCR_END(Rc);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f::Floating Multiply-Add Single
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
1995-11-01 19:32:38 +00:00
0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
1995-11-01 19:32:38 +00:00
0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract Single
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
1995-11-01 19:32:38 +00:00
0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
1995-11-01 19:32:38 +00:00
0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add Single
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
1995-11-01 19:32:38 +00:00
0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 5, 5, 0
*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 2, 4, 0
*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
1995-11-01 19:32:38 +00:00
0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract Single
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
1995-11-01 19:32:38 +00:00
#
# I.4.6.6 Floating-Point Rounding and Conversion Instructions
#
0.63,6.FRT,11./,16.FRB,21.12,31.Rc:X:f::Floating Round to Single-Precision
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
1995-11-01 19:32:38 +00:00
int sign;
int exp;
unsigned64 frac_grx;
/* split off cases for what to do */
if (EXTRACTED64(*frB, 1, 11) < 897
&& EXTRACTED64(*frB, 1, 63) > 0) {
if ((FPSCR & fpscr_ue) == 0) goto Disabled_Exponent_Underflow;
if ((FPSCR & fpscr_ue) != 0) goto Enabled_Exponent_Underflow;
}
if (EXTRACTED64(*frB, 1, 11) > 1150
&& EXTRACTED64(*frB, 1, 11) < 2047) {
if ((FPSCR & fpscr_oe) == 0) goto Disabled_Exponent_Overflow;
if ((FPSCR & fpscr_oe) != 0) goto Enabled_Exponent_Overflow;
}
if (EXTRACTED64(*frB, 1, 11) > 896
&& EXTRACTED64(*frB, 1, 11) < 1151) goto Normal_Operand;
if (EXTRACTED64(*frB, 1, 63) == 0) goto Zero_Operand;
if (EXTRACTED64(*frB, 1, 11) == 2047) {
if (EXTRACTED64(*frB, 12, 63) == 0) goto Infinity_Operand;
if (EXTRACTED64(*frB, 12, 12) == 1) goto QNaN_Operand;
if (EXTRACTED64(*frB, 12, 12) == 0
&& EXTRACTED64(*frB, 13, 63) > 0) goto SNaN_Operand;
}
/* handle them */
Disabled_Exponent_Underflow:
sign = EXTRACTED64(*frB, 0, 0);
if (EXTRACTED64(*frB, 1, 11) == 0) {
exp = -1022;
frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
}
if (EXTRACTED64(*frB, 1, 11) > 0) {
exp = EXTRACTED64(*frB, 1, 11) - 1023;
frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
}
Denormalize_Operand:
/* G|R|X == zero from above */
while (exp < -126) {
exp = exp - 1;
frac_grx = (INSERTED64(EXTRACTED64(frac_grx, 0, 54), 1, 55)
| MASKED64(frac_grx, 55, 55));
}
FPSCR_SET_UX(EXTRACTED64(frac_grx, 24, 55) > 0);
Round_Single(processor, sign, &exp, &frac_grx);
FPSCR_SET_XX(FPSCR & fpscr_fi);
if (EXTRACTED64(frac_grx, 0, 52) == 0) {
*frT = INSERTED64(sign, 0, 0);
if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
}
if (EXTRACTED64(frac_grx, 0, 52) > 0) {
if (EXTRACTED64(frac_grx, 0, 0) == 1) {
if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
}
if (EXTRACTED64(frac_grx, 0, 0) == 0) {
if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_denormalized_number);
if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_denormalized_number);
}
/*Normalize_Operand:*/
while (EXTRACTED64(frac_grx, 0, 0) == 0) {
exp = exp - 1;
frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1, 52), 0, 51);
}
*frT = (INSERTED64(sign, 0, 0)
| INSERTED64(exp + 1023, 1, 11)
| INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
}
goto Done;
Enabled_Exponent_Underflow:
FPSCR_SET_UX(1);
sign = EXTRACTED64(*frB, 0, 0);
if (EXTRACTED64(*frB, 1, 11) == 0) {
exp = -1022;
frac_grx = INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
}
if (EXTRACTED64(*frB, 1, 11) > 0) {
exp = EXTRACTED64(*frB, 1, 11) - 1023;
frac_grx = (BIT64(0) |
INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52));
}
/*Normalize_Operand:*/
while (EXTRACTED64(frac_grx, 0, 0) == 0) {
exp = exp - 1;
frac_grx = INSERTED64(EXTRACTED64(frac_grx, 1, 52), 0, 51);
}
Round_Single(processor, sign, &exp, &frac_grx);
FPSCR_SET_XX(FPSCR & fpscr_fi);
exp = exp + 192;
*frT = (INSERTED64(sign, 0, 0)
| INSERTED64(exp + 1023, 1, 11)
| INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
goto Done;
Disabled_Exponent_Overflow:
FPSCR_SET_OX(1);
if ((FPSCR & fpscr_rn) == fpscr_rn_round_to_nearest) {
if (EXTRACTED64(*frB, 0, 0) == 0) {
*frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
}
if (EXTRACTED64(*frB, 0, 0) == 1) {
*frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
}
}
if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_zero) {
if (EXTRACTED64(*frB, 0, 0) == 0) {
*frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
}
if (EXTRACTED64(*frB, 0, 0) == 1) {
*frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
}
}
if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_pos_infinity) {
if (EXTRACTED64(*frB, 0, 0) == 0) {
*frT = INSERTED64(0x7FF00000, 0, 31) | 0x00000000;
FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
}
if (EXTRACTED64(*frB, 0, 0) == 1) {
*frT = INSERTED64(0xC7EFFFFF, 0, 31) | 0xE0000000;
FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
}
}
if ((FPSCR & fpscr_rn) == fpscr_rn_round_towards_neg_infinity) {
if (EXTRACTED64(*frB, 0, 0) == 0) {
*frT = INSERTED64(0x47EFFFFF, 0, 31) | 0xE0000000;
FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
}
if (EXTRACTED64(*frB, 0, 0) == 1) {
*frT = INSERTED64(0xFFF00000, 0, 31) | 0x00000000;
FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
}
}
/* FPSCR[FR] <- undefined */
FPSCR_SET_FI(1);
FPSCR_SET_XX(1);
goto Done;
Enabled_Exponent_Overflow:
sign = EXTRACTED64(*frB, 0, 0);
exp = EXTRACTED64(*frB, 1, 11) - 1023;
frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
Round_Single(processor, sign, &exp, &frac_grx);
FPSCR_SET_XX(FPSCR & fpscr_fi);
Enabled_Overflow:
FPSCR_SET_OX(1);
exp = exp - 192;
*frT = (INSERTED64(sign, 0, 0)
| INSERTED64(exp + 1023, 1, 11)
| INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
goto Done;
Zero_Operand:
*frT = *frB;
if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_zero);
if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_zero);
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
goto Done;
Infinity_Operand:
*frT = *frB;
if (EXTRACTED64(*frB, 0, 0) == 0) FPSCR_SET_FPRF(fpscr_rf_pos_infinity);
if (EXTRACTED64(*frB, 0, 0) == 1) FPSCR_SET_FPRF(fpscr_rf_neg_infinity);
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
goto Done;
QNaN_Operand:
*frT = INSERTED64(EXTRACTED64(*frB, 0, 34), 0, 34);
FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
goto Done;
SNaN_Operand:
FPSCR_OR_VX(fpscr_vxsnan);
if ((FPSCR & fpscr_ve) == 0) {
*frT = (MASKED64(*frB, 0, 11)
| BIT64(12)
| MASKED64(*frB, 13, 34));
FPSCR_SET_FPRF(fpscr_rf_quiet_nan);
}
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
goto Done;
Normal_Operand:
sign = EXTRACTED64(*frB, 0, 0);
exp = EXTRACTED64(*frB, 1, 11) - 1023;
frac_grx = BIT64(0) | INSERTED64(EXTRACTED64(*frB, 12, 63), 1, 52);
Round_Single(processor, sign, &exp, &frac_grx);
FPSCR_SET_XX(FPSCR & fpscr_fi);
if (exp > 127 && (FPSCR & fpscr_oe) == 0) goto Disabled_Exponent_Overflow;
if (exp > 127 && (FPSCR & fpscr_oe) != 0) goto Enabled_Overflow;
*frT = (INSERTED64(sign, 0, 0)
| INSERTED64(exp + 1023, 1, 11)
| INSERTED64(EXTRACTED64(frac_grx, 1, 52), 12, 63));
if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_neg_normal_number);
goto Done;
Done:
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.63,6.FRT,11./,16.FRB,21.814,31.Rc:X:64,f::Floating Convert To Integer Doubleword
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.63,6.FRT,11./,16.FRB,21.815,31.Rc:X:64,f::Floating Convert To Integer Doubleword with round towards Zero
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.63,6.FRT,11./,16.FRB,21.14,31.Rc:X:f::Floating Convert To Integer Word
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.63,6.FRT,11./,16.FRB,21.15,31.Rc:X:f:fctiwz:Floating Convert To Integer Word with round towards Zero
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
1995-11-01 19:32:38 +00:00
FPSCR_BEGIN;
convert_to_integer(processor, cia,
frT, *frB,
fpscr_rn_round_towards_zero, 32);
FPSCR_END(Rc);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.63,6.FRT,11./,16.FRB,21.846,31.Rc:X:64,f::Floating Convert from Integer Doubleword
int sign = EXTRACTED64(*frB, 0, 0);
int exp = 63;
unsigned64 frac = *frB;
if (frac == 0) goto Zero_Operand;
if (sign == 1) frac = ~frac + 1;
while (EXTRACTED64(frac, 0, 0) == 0) {
/*??? do the loop 0 times if (FRB) = max negative integer */
frac = INSERTED64(EXTRACTED64(frac, 1, 63), 0, 62);
exp = exp - 1;
}
Round_Float(processor, sign, &exp, &frac, FPSCR & fpscr_rn);
if (sign == 0) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
if (sign == 1) FPSCR_SET_FPRF(fpscr_rf_pos_normal_number);
*frT = (INSERTED64(sign, 0, 0)
| INSERTED64(exp + 1023, 1, 11)
| INSERTED64(EXTRACTED64(frac, 1, 52), 12, 63));
goto Done;
/**/
Zero_Operand:
FPSCR_SET_FR(0);
FPSCR_SET_FI(0);
FPSCR_SET_FPRF(fpscr_rf_pos_zero);
*frT = 0;
goto Done;
/**/
Done:
#
# I.4.6.7 Floating-Point Compare Instructions
#
0.63,6.BF,9./,11.FRA,16.FRB,21.0,31./:X:f:fcmpu:Floating Compare Unordered
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
1995-11-01 19:32:38 +00:00
FPSCR_BEGIN;
unsigned c;
if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
else if (is_less_than(frA, frB))
c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
else if (is_greater_than(frA, frB))
c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
else
c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
FPSCR_SET_FPCC(c);
CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0))
FPSCR_OR_VX(fpscr_vxsnan);
FPSCR_END(0);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.63,6.BF,9./,11.FRA,16.FRB,21.32,31./:X:f:fcmpo:Floating Compare Ordered
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_FPU, PPC_UNIT_FPU, 4, 4, 0
*603: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*603e:PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
*604: PPC_UNIT_FPU, PPC_UNIT_FPU, 1, 3, 0
1995-11-01 19:32:38 +00:00
FPSCR_BEGIN;
unsigned c;
if (is_NaN(*frA, 0) || is_NaN(*frB, 0))
c = cr_i_summary_overflow; /* 0b0001 - (FRA) ? (FRB) */
else if (is_less_than(frA, frB))
c = cr_i_negative; /* 0b1000 - (FRA) < (FRB) */
else if (is_greater_than(frA, frB))
c = cr_i_positive; /* 0b0100 - (FRA) > (FRB) */
else
c = cr_i_zero; /* 0b0010 - (FRA) = (FRB) */
FPSCR_SET_FPCC(c);
CR_SET(BF, c); /* CR[4*BF..4*BF+3] = c */
if (is_SNaN(*frA, 0) || is_SNaN(*frB, 0)) {
FPSCR_OR_VX(fpscr_vxsnan);
if ((FPSCR & fpscr_ve) == 0)
FPSCR_OR_VX(fpscr_vxvc);
}
else if (is_QNaN(*frA, 0) || is_QNaN(*frB, 0)) {
FPSCR_OR_VX(fpscr_vxvc);
}
FPSCR_END(0);
#
# I.4.6.8 Floating-Point Status and Control Register Instructions
#
0.63,6.FRT,11./,16./,21.583,31.Rc:X:f::Move From FPSCR
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.63,6.BF,9./,11.BFA,14./,16./,21.64,31./:X:f::Move to Condition Register from FPSCR
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.64,6.BF,9./,11./,16.U,20./,21.134,31.Rc:X:f::Move To FPSCR Field Immediate
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.63,6./,7.FLM,15./,16.FRB,21.711,31.Rc:XFL:f::Move To FPSCR Fields
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.63,6.BT,11./,16./,21.70,31.Rc:X:f::Move To FPSCR Bit 0
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.63,6.BT,11./,16./,21.38,31.Rc:X:f::Move To FPSCR Bit 1
#
# I.A.1.1 Floating-Point Store Instruction
#
0.31,6.FRS,11.RA,16.RB,21.983,31./:X:f::Store Floating-Point as Integer Word Indexed
#
# I.A.1.2 Floating-Point Arithmetic Instructions
#
0.63,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f::Floating Square Root
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.59,6.FRT,11./,16.FRB,21./,26.22,31.Rc:A:f::Floating Square Root Single
0.59,6.FRT,11./,16.FRB,21./,26.24,31.Rc:A:f::Floating Reciprocal Estimate Single
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.63,6.FRT,11./,16.FRB,21./,26.26,31.Rc:A:f::Floating Reciprocal Square Root Estimate
#
# I.A.1.3 Floating-Point Select Instruction
#
0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.23,31.Rc:A:f::Floating Select
#
# II.3.2 Cache Management Instructions
#
0.31,6./,11.RA,16.RB,21.982,31./:X::icbi:Instruction Cache Block Invalidate
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, PPC_SERIALIZE
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, PPC_SERIALIZE
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, PPC_SERIALIZE
1995-11-15 22:53:59 +00:00
/* blindly flush all instruction cache entries */
#if WITH_IDECODE_CACHE_SIZE
cpu_flush_icache(processor);
#endif
1995-11-01 19:32:38 +00:00
0.19,6./,11./,16./,21.150,31./:XL::isync:Instruction Synchronize
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, PPC_SERIALIZE
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, PPC_SERIALIZE
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, PPC_SERIALIZE
1995-11-01 19:32:38 +00:00
cpu_synchronize_context(processor);
#
# II.3.2.2 Data Cache Instructions
#
0.31,6./,11.RA,16.RB,21.278,31./:X:::Data Cache Block Touch
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, PPC_SERIALIZE
TRACE(trace_tbd,("Data Cache Block Touch\n"));
1995-11-03 19:37:28 +00:00
1995-11-01 19:32:38 +00:00
0.31,6./,11.RA,16.RB,21.246,31./:X:::Data Cache Block Touch for Store
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, PPC_SERIALIZE
TRACE(trace_tbd,("Data Cache Block Touch for Store\n"));
1995-11-03 19:37:28 +00:00
1995-11-01 19:32:38 +00:00
0.31,6./,11.RA,16.RB,21.1014,31./:X:::Data Cache Block set to Zero
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 10, 10, PPC_SERIALIZE
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 10, 10, PPC_SERIALIZE
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, PPC_SERIALIZE
TRACE(trace_tbd,("Data Cache Block set to Zero\n"));
1995-11-03 19:37:28 +00:00
1995-11-01 19:32:38 +00:00
0.31,6./,11.RA,16.RB,21.54,31./:X:::Data Cache Block Store
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, PPC_SERIALIZE
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, PPC_SERIALIZE
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, PPC_SERIALIZE
TRACE(trace_tbd,("Data Cache Block Store\n"));
1995-11-03 19:37:28 +00:00
1995-11-01 19:32:38 +00:00
0.31,6./,11.RA,16.RB,21.86,31./:X:::Data Cache Block Flush
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, PPC_SERIALIZE
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, PPC_SERIALIZE
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, PPC_SERIALIZE
TRACE(trace_tbd,("Data Cache Block Flush\n"));
1995-11-01 19:32:38 +00:00
#
1995-11-16 19:02:52 +00:00
# II.3.3 Enforce In-order Execution of I/O Instruction
1995-11-01 19:32:38 +00:00
#
0.31,6./,11./,16./,21.854,31./:X::eieio:Enforce In-order Execution of I/O
/* Since this model has no instruction overlap
this instruction need do nothing */
#
# II.4.1 Time Base Instructions
#
0.31,6.RT,11.tbr,21.371,31./:XFX::mftb:Move From Time Base
1995-11-16 19:02:52 +00:00
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
1995-11-01 19:32:38 +00:00
int n = (tbr{5:9} << 5) | tbr{0:4};
if (n == 268) {
if (is_64bit_implementation) *rT = TB;
else *rT = EXTRACTED64(TB, 32, 63);
}
else if (n == 269) {
if (is_64bit_implementation) *rT = EXTRACTED64(TB, 0, 31);
else *rT = EXTRACTED64(TB, 0, 31);
}
else
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
#
# III.2.3.1 System Linkage Instructions
#
1995-11-15 22:53:59 +00:00
0.19,6./,11./,16./,21.50,31./:XL::rfi:Return From Interrupt
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, PPC_SERIALIZE
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, PPC_SERIALIZE
*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, PPC_SERIALIZE
1995-11-15 22:53:59 +00:00
if (IS_PROBLEM_STATE(processor)) {
program_interrupt(processor, cia,
privileged_instruction_program_interrupt);
}
else {
MSR = (MASKED(SRR1, 0, 32)
| MASKED(SRR1, 37, 41)
| MASKED(SRR1, 48, 63));
NIA = MASKED(SRR0, 0, 61);
cpu_synchronize_context(processor);
}
1995-11-01 19:32:38 +00:00
#
# III.3.4.1 Move to/from System Register Instructions
#
#0.31,6.RS,11.spr,21.467,31./:XFX:::Move To Special Purpose Register
#0.31,6.RT,11.spr,21.339,31./:XFX:::Move From Special Purpose Register
0.31,6.RS,11./,16./,21.146,31./:X:::Move To Machine State Register
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, PPC_SERIALIZE
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, PPC_SERIALIZE
*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, PPC_SERIALIZE
1995-11-01 19:32:38 +00:00
if (IS_PROBLEM_STATE(processor))
program_interrupt(processor, cia,
privileged_instruction_program_interrupt);
else
MSR = *rS;
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11./,16./,21.83,31./:X:::Move From Machine State Register
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, PPC_SERIALIZE
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, PPC_SERIALIZE
*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, PPC_SERIALIZE
1995-11-01 19:32:38 +00:00
if (IS_PROBLEM_STATE(processor))
program_interrupt(processor, cia,
privileged_instruction_program_interrupt);
else
*rT = MSR;
#
# III.4.11.1 Cache Management Instructions
#
0.31,6./,11.RA,16.RB,21.470,31./:X::dcbi:Data Cache Block Invalidate
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, PPC_SERIALIZE
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, PPC_SERIALIZE
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 2, 2, PPC_SERIALIZE
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, PPC_SERIALIZE
if (IS_PROBLEM_STATE(processor))
program_interrupt(processor, cia,
privileged_instruction_program_interrupt);
else
TRACE(trace_tbd,("Data Cache Block Invalidate\n"));
1995-11-01 19:32:38 +00:00
#
# III.4.11.2 Segment Register Manipulation Instructions
#
0.31,6.RS,11./,12.SR,16./,21.210,31./:X:32:mtsr %SR,%RS:Move To Segment Register
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, PPC_SERIALIZE
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, PPC_SERIALIZE
*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, PPC_SERIALIZE
1995-11-01 19:32:38 +00:00
if (IS_PROBLEM_STATE(processor))
program_interrupt(processor, cia,
privileged_instruction_program_interrupt);
else
SEGREG(SR) = *rS;
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11./,16.RB,21.242,31./:X:32:mtsrin %RS,%RB:Move To Segment Register Indirect
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, PPC_SERIALIZE
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 2, 2, PPC_SERIALIZE
*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, PPC_SERIALIZE
1995-11-01 19:32:38 +00:00
if (IS_PROBLEM_STATE(processor))
program_interrupt(processor, cia,
privileged_instruction_program_interrupt);
else
SEGREG(EXTRACTED32(*rB, 0, 3)) = *rS;
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11./,12.SR,16./,21.595,31./:X:32:mfsr %RT,%RS:Move From Segment Register
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, PPC_SERIALIZE
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, PPC_SERIALIZE
*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, PPC_SERIALIZE
1995-11-01 19:32:38 +00:00
if (IS_PROBLEM_STATE(processor))
program_interrupt(processor, cia,
privileged_instruction_program_interrupt);
else
*rT = SEGREG(SR);
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RT,11./,16.RB,21.659,31./:X:32:mfsrin %RT,%RB:Move From Segment Register Indirect
1995-11-16 19:02:52 +00:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, PPC_SERIALIZE
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, PPC_SERIALIZE
*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, PPC_SERIALIZE
1995-11-01 19:32:38 +00:00
if (IS_PROBLEM_STATE(processor))
program_interrupt(processor, cia,
privileged_instruction_program_interrupt);
else
*rT = SEGREG(EXTRACTED32(*rB, 0, 3));
#
# III.4.11.3 Lookaside Buffer Management Instructions (Optional)
#
0.31,6./,11./,16.RB,21.434,31./:X:64::SLB Invalidate Entry
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6./,11./,16./,21.498,31./:X:64::SLB Invalidate All
0.31,6./,11./,16.RB,21.306,31./:X:::TLB Invalidate Entry
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6./,11./,16./,21.370,31./:X:::TLB Invalidate All
0.31,6./,11./,16./,21.566,31./:X:::TLB Sychronize
#
# III.A.1.2 External Access Instructions
#
0.31,6.RT,11.RA,16.RB,21.310,31./:X:earwax::External Control In Word Indexed
1995-11-16 19:02:52 +00:00
1995-11-01 19:32:38 +00:00
0.31,6.RS,11.RA,16.RB,21.438,31./:X:earwax::External Control Out Word Indexed