binutils-gdb/sim/ppc/ppc-instructions

4082 lines
138 KiB
Plaintext
Raw Normal View History

1995-11-01 20:32:38 +01: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
#
#
# 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 20:02:52 +01:00
1995-11-15 23:53:59 +01:00
# PowerPC models
1995-11-18 02:14:45 +01: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
# Flags for model.h
1995-11-15 23:53:59 +01:00
::model-data:::
typedef enum _ppc_function_unit {
1995-11-16 20:02:52 +01: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 23:53:59 +01:00
nr_ppc_function_units
} ppc_function_unit;
1995-11-16 20:02:52 +01:00
1995-11-15 23:53:59 +01:00
/* Structure to hold timing information on a per instruction basis */
struct _model_time {
1995-11-17 20:17:58 +01:00
ppc_function_unit first_unit; /* first functional unit this insn could use */
ppc_function_unit last_unit; /* last functional unit this insn could use */
signed16 issue; /* # cycles before function unit can process other insns */
signed16 done; /* # cycles before insn is done */
1995-11-18 02:14:45 +01:00
unsigned32 flags; /* any flags that are needed */
1995-11-15 23:53:59 +01:00
};
1995-11-16 20:02:52 +01:00
1995-11-17 20:17:58 +01:00
/* Register mappings */
#define PPC_INT_REG 0 /* start of integer registers */
#define PPC_FLOAT_REG (PPC_INT_REG + 32) /* start of floating point registers */
#define PPC_CR_REG (PPC_FLOAT_REG + 32) /* start of CR0 .. CR7 */
#define PPC_SPR_REG (PPC_CR_REG + 8) /* start of special purpose registers */
#define PPC_FPSCR_REG (PPC_SPR_REG + 1024) /* start of fpscr register */
#define NR_PPC_REGS (PPC_FPSCR_REG + 1) /* # of registers to allocate */
/* Structure for each register to indicate whether it is free or not */
typedef struct _model_reg model_reg;
struct _model_reg {
model_reg *next; /* next register to be released */
int in_use; /* non zero if register is used */
};
/* Structure for each functional unit that is busy */
typedef struct _model_busy model_busy;
struct _model_busy {
model_busy *next; /* next function unit */
model_reg *reg; /* list of registers to release */
ppc_function_unit unit; /* function unit name */
signed16 issue; /* # of cycles until unit can accept another insn */
signed16 done; /* # of cycles until insn is done */
};
1995-11-16 20:02:52 +01:00
1995-11-15 23:53:59 +01:00
/* Structure to hold the current state information for the simulated CPU model */
struct _model_data {
1995-11-17 20:17:58 +01:00
cpu *processor; /* point back to processor */
1995-11-15 23:53:59 +01:00
const char *name; /* model name */
const model_time *timing; /* timing information */
1995-11-17 20:17:58 +01:00
model_busy *busy_list; /* list of busy function units */
model_busy *free_list; /* list of model_busy structs not in use */
model_reg registers[NR_PPC_REGS]; /* register status */
unsigned32 busy_mask; /* bitmask of busy function units */
count_type nr_cycles; /* # cycles */
count_type nr_branches; /* # branches */
count_type nr_branches_fallthrough; /* # conditional branches that fell through */
count_type nr_branch_predict_trues; /* # branches predicted correctly */
count_type nr_branch_predict_falses; /* # branches predicted incorrectly */
1995-11-18 02:14:45 +01:00
count_type nr_stalls_data; /* # of stalls for data */
count_type nr_stalls_unit; /* # of stalls waiting for a function unit */
count_type nr_stalls_serialize; /* # of stalls waiting for things to quiet down */
count_type nr_insns_not_handled; /* # of instructions not handled */
1995-11-17 20:17:58 +01:00
count_type nr_units[nr_ppc_function_units]; /* function unit counts */
1995-11-18 02:14:45 +01:00
int insn_handled; /* whether last insn was handled */
1995-11-15 23:53:59 +01:00
};
1995-11-16 20:02:52 +01:00
1995-11-15 23:53:59 +01:00
STATIC_MODEL const char *const ppc_function_unit_name[ (int)nr_ppc_function_units ] = {
1995-11-16 20:02:52 +01: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 23:53:59 +01:00
};
1995-11-18 02:14:45 +01:00
# Code called after executing the semantics of the function
void::model-function::model_cleanup:itable_index index, model_data *model_ptr
if (model_ptr->insn_handled)
model_ptr->insn_handled = 0;
else {
model_ptr->nr_insns_not_handled++;
TRACE(trace_tbd,("model specific code for %s not done\n", itable[index].name));
}
1995-11-17 20:17:58 +01:00
# Advance state to next cycle, releasing any registers allocated
void::model-internal::model_new_cycle:model_data *model_ptr
model_busy *cur_busy = model_ptr->busy_list;
model_busy *free_list = model_ptr->free_list;
model_busy *next_busy = (model_busy *)0;
unsigned32 busy_mask = model_ptr->busy_mask;
model_busy *next;
model_ptr->nr_cycles++;
for ( ; cur_busy; cur_busy = next) {
next = cur_busy->next;
if (--cur_busy->done <= 0) { /* function unit done, release registers */
model_reg *reg = cur_busy->reg;
TRACE(trace_model,("done, retiring %s\n", ppc_function_unit_name[cur_busy->unit]));
while (reg) {
TRACE(trace_model,("freeing up reg, address 0x%lx (%d)\n", (long)reg, reg - &model_ptr->registers[0]));
reg->in_use = 0;
reg = reg->next;
}
busy_mask &= ~(1 << cur_busy->unit);
cur_busy->next = free_list;
free_list = cur_busy;
}
else if (--cur_busy->issue <= 0) { /* function unit pipelined, allow new use */
TRACE(trace_model,("pipeline, %s ready for next client\n", ppc_function_unit_name[cur_busy->unit]));
busy_mask &= ~(1 << cur_busy->unit);
cur_busy->next = next_busy;
next_busy = cur_busy;
}
else {
TRACE(trace_model,("%s still working, issue = %d, done = %d\n",
ppc_function_unit_name[cur_busy->unit],
cur_busy->issue,
cur_busy->done));
cur_busy->next = next_busy;
next_busy = cur_busy;
}
}
model_ptr->busy_list = next_busy;
model_ptr->free_list = free_list;
model_ptr->busy_mask = busy_mask;
# Mark a function unit as busy, return the busy structure so regs can be added to be released
model_busy *::model-internal::model_make_busy:model_data *model_ptr, ppc_function_unit unit, int issue, int done
model_busy *busy;
TRACE(trace_model,("unit = %s, issue = %d, done = %d\n", ppc_function_unit_name[unit], issue, done));
1995-11-18 02:14:45 +01:00
model_ptr->insn_handled = 1;
1995-11-17 20:17:58 +01:00
if (!model_ptr->free_list) {
busy = ZALLOC(model_busy);
1995-11-16 20:02:52 +01:00
}
1995-11-15 23:53:59 +01:00
else {
1995-11-17 20:17:58 +01:00
busy = model_ptr->free_list;
model_ptr->free_list = busy->next;
busy->reg = (model_reg *)0;
}
busy->next = model_ptr->busy_list;
busy->unit = unit;
busy->issue = issue;
busy->done = done;
model_ptr->busy_list = busy;
1995-11-18 02:14:45 +01:00
model_ptr->busy_mask |= (1 << unit);
model_ptr->nr_units[unit]++;
1995-11-17 20:17:58 +01:00
return busy;
1995-11-18 02:14:45 +01:00
# Wait until a function unit is non-busy, and then allocate a busy pointer & return the pointer
model_busy *::model-internal::model_wait_for_unit:itable_index index, model_data *const model_ptr, const model_time *const time_ptr
ppc_function_unit first_unit = time_ptr->first_unit;
ppc_function_unit last_unit = time_ptr->last_unit;
1995-11-17 20:17:58 +01:00
ppc_function_unit unit;
1995-11-18 02:14:45 +01:00
int stall_increment = 0;
1995-11-17 20:17:58 +01:00
for (;;) {
unsigned32 busy_mask = model_ptr->busy_mask;
for (unit = first_unit; unit <= last_unit; unit++) {
if (((1 << unit) & busy_mask) == 0) {
1995-11-18 02:14:45 +01:00
return model_make_busy(model_ptr, unit,
1995-11-17 20:17:58 +01:00
model_ptr->timing[index].issue,
model_ptr->timing[index].done);
}
}
1995-11-18 02:14:45 +01:00
TRACE(trace_model,("all function units are busy for %s\n", itable[index].name));
model_ptr->nr_stalls_unit += stall_increment; /* don't count first stall */
stall_increment = 1;
1995-11-17 20:17:58 +01:00
model_new_cycle(model_ptr);
1995-11-15 23:53:59 +01:00
}
1995-11-18 02:14:45 +01:00
# Serialize the processor, waiting for all instructions to drain out before adding an instruction.
void::model-function::model_serialize:itable_index index, model_data *model_ptr
while (model_ptr->busy_list) {
TRACE(trace_model,("waiting for pipeline to empty\n"));
model_ptr->nr_stalls_serialize++;
model_new_cycle(model_ptr);
}
(void) model_make_busy(model_ptr,
model_ptr->timing[index].first_unit,
model_ptr->timing[index].issue,
model_ptr->timing[index].done);
# Wait for a CR to become unbusy
void::model-function::model_wait_for_cr:model_data *model_ptr, unsigned CRBIT
unsigned u;
int cr_var = 0;
for (u = 0xc0000000; (u != 0) && (CRBIT & u) == 0; u >>= 4 )
cr_var++;
while (model_ptr->registers[cr_var + PPC_CR_REG].in_use) {
TRACE(trace_model,("waiting for CR %d\n", cr_var));
model_ptr->nr_stalls_data++;
model_new_cycle(model_ptr);
}
# Schedule an instruction that takes 2 integer input registers and produces an output register & possibly sets CR0
void::model-function::ppc_insn_int2:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rD, signed_word *rA, signed_word *rB, unsigned Rc
if (!WITH_MODEL_ISSUE)
return;
else {
registers *cpu_regs = cpu_registers(processor);
const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
const unsigned ppc_RB = (rB - &cpu_regs->gpr[0]) + PPC_INT_REG;
const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
model_reg *ppc_regs = model_ptr->registers;
model_busy *busy_ptr;
if (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
model_new_cycle(model_ptr); /* don't count first dependency as a stall */
while (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
model_ptr->nr_stalls_data++;
model_new_cycle(model_ptr);
}
}
busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
ppc_regs[ppc_RD].next = (model_reg *)0;
ppc_regs[ppc_RD].in_use = 1;
if (!Rc)
busy_ptr->reg = &ppc_regs[ppc_RD];
else {
model_reg *reg_CR0 = &ppc_regs[0 + PPC_CR_REG];
reg_CR0->next = &ppc_regs[ppc_RD];
busy_ptr->reg = reg_CR0;
}
}
# Schedule an instruction that takes 1 integer input registers and produces an output register & possibly sets CR0
void::model-function::ppc_insn_int1:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rD, signed_word *rA, unsigned Rc
if (!WITH_MODEL_ISSUE)
return;
else {
registers *cpu_regs = cpu_registers(processor);
const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
model_reg *ppc_regs = model_ptr->registers;
model_busy *busy_ptr;
if (ppc_regs[ppc_RA].in_use) {
model_new_cycle(model_ptr); /* don't count first dependency as a stall */
while (ppc_regs[ppc_RA].in_use) {
model_ptr->nr_stalls_data++;
model_new_cycle(model_ptr);
}
}
busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
ppc_regs[ppc_RD].next = (model_reg *)0;
ppc_regs[ppc_RD].in_use = 1;
if (!Rc)
busy_ptr->reg = &ppc_regs[ppc_RD];
else {
model_reg *reg_CR0 = &ppc_regs[0 + PPC_CR_REG];
reg_CR0->next = &ppc_regs[ppc_RD];
busy_ptr->reg = reg_CR0;
}
}
# Schedule an instruction that takes no integer input registers and produces an output register & possibly sets CR0
void::model-function::ppc_insn_int0:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rD, unsigned Rc
if (!WITH_MODEL_ISSUE)
return;
else {
registers *cpu_regs = cpu_registers(processor);
const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
model_reg *ppc_regs = model_ptr->registers;
model_busy *busy_ptr;
busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
ppc_regs[ppc_RD].next = (model_reg *)0;
ppc_regs[ppc_RD].in_use = 1;
if (!Rc)
busy_ptr->reg = &ppc_regs[ppc_RD];
else {
model_reg *reg_CR0 = &ppc_regs[0 + PPC_CR_REG];
reg_CR0->next = &ppc_regs[ppc_RD];
busy_ptr->reg = reg_CR0;
}
}
# Schedule an instruction that takes 2 integer input registers and produces an output register & updates a second register
void::model-function::ppc_insn_int2_update:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rD, signed_word *rA, signed_word *rB
if (!WITH_MODEL_ISSUE)
return;
else {
registers *cpu_regs = cpu_registers(processor);
const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
const unsigned ppc_RB = (rB - &cpu_regs->gpr[0]) + PPC_INT_REG;
const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
model_reg *ppc_regs = model_ptr->registers;
model_busy *busy_ptr;
if (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
model_new_cycle(model_ptr); /* don't count first dependency as a stall */
while (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
model_ptr->nr_stalls_data++;
model_new_cycle(model_ptr);
}
}
busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
ppc_regs[ppc_RA].next = (model_reg *)0;
ppc_regs[ppc_RA].in_use = 1;
ppc_regs[ppc_RD].next = &ppc_regs[ppc_RA];
ppc_regs[ppc_RD].in_use = 1;
busy_ptr->reg = &ppc_regs[ppc_RD];
}
# Schedule an instruction that takes 1 integer input registers and produces an output register & updates the other register
void::model-function::ppc_insn_int1_update:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rD, signed_word *rA
if (!WITH_MODEL_ISSUE)
return;
else {
registers *cpu_regs = cpu_registers(processor);
const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
model_reg *ppc_regs = model_ptr->registers;
model_busy *busy_ptr;
if (ppc_regs[ppc_RA].in_use) {
model_new_cycle(model_ptr); /* don't count first dependency as a stall */
while (ppc_regs[ppc_RA].in_use) {
model_ptr->nr_stalls_data++;
model_new_cycle(model_ptr);
}
}
busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
ppc_regs[ppc_RA].next = (model_reg *)0;
ppc_regs[ppc_RA].in_use = 1;
ppc_regs[ppc_RD].next = &ppc_regs[ppc_RA];
ppc_regs[ppc_RD].in_use = 1;
busy_ptr->reg = &ppc_regs[ppc_RD];
}
# Schedule an instruction that takes 2 integer input registers and produces no output register
void::model-function::ppc_insn_int2_noout:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rA, signed_word *rB
if (!WITH_MODEL_ISSUE)
return;
else {
registers *cpu_regs = cpu_registers(processor);
const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
const unsigned ppc_RB = (rB - &cpu_regs->gpr[0]) + PPC_INT_REG;
model_reg *ppc_regs = model_ptr->registers;
if (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
model_new_cycle(model_ptr); /* don't count first dependency as a stall */
while (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
model_ptr->nr_stalls_data++;
model_new_cycle(model_ptr);
}
}
(void) model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
}
# Schedule an instruction that takes 1 integer input registers and produces no output register
void::model-function::ppc_insn_int1_noout:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rA
if (!WITH_MODEL_ISSUE)
return;
else {
registers *cpu_regs = cpu_registers(processor);
const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
model_reg *ppc_regs = model_ptr->registers;
if (ppc_regs[ppc_RA].in_use) {
model_new_cycle(model_ptr); /* don't count first dependency as a stall */
while (ppc_regs[ppc_RA].in_use) {
model_ptr->nr_stalls_data++;
model_new_cycle(model_ptr);
}
}
(void) model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
}
# Schedule an instruction that takes no input registers and produces no output
void::model-function::ppc_insn_int0_noout:itable_index index, cpu *processor, model_data *model_ptr
if (!WITH_MODEL_ISSUE)
return;
else {
(void) model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
}
# Schedule an instruction that takes 2 integer input registers and produces a CR output register
void::model-function::ppc_insn_int2_cr:itable_index index, cpu *processor, model_data *model_ptr, unsigned CRD, signed_word *rA, signed_word *rB
if (!WITH_MODEL_ISSUE)
return;
else {
registers *cpu_regs = cpu_registers(processor);
const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
const unsigned ppc_RB = (rB - &cpu_regs->gpr[0]) + PPC_INT_REG;
const unsigned ppc_CRD = CRD + PPC_CR_REG;
model_reg *ppc_regs = model_ptr->registers;
model_busy *busy_ptr;
if (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
model_new_cycle(model_ptr); /* don't count first dependency as a stall */
while (ppc_regs[ppc_RA].in_use | ppc_regs[ppc_RB].in_use) {
model_ptr->nr_stalls_data++;
model_new_cycle(model_ptr);
}
}
busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
ppc_regs[ppc_CRD].next = (model_reg *)0;
ppc_regs[ppc_CRD].in_use = 1;
busy_ptr->reg = &ppc_regs[ppc_CRD];
}
# Schedule an instruction that takes 1 integer input register and produces a CR output register
void::model-function::ppc_insn_int1_cr:itable_index index, cpu *processor, model_data *model_ptr, unsigned CRD, signed_word *rA
if (!WITH_MODEL_ISSUE)
return;
else {
registers *cpu_regs = cpu_registers(processor);
const unsigned ppc_RA = (rA - &cpu_regs->gpr[0]) + PPC_INT_REG;
const unsigned ppc_CRD = CRD + PPC_CR_REG;
model_reg *ppc_regs = model_ptr->registers;
model_busy *busy_ptr;
if (ppc_regs[ppc_RA].in_use) {
model_new_cycle(model_ptr); /* don't count first dependency as a stall */
while (ppc_regs[ppc_RA].in_use) {
model_ptr->nr_stalls_data++;
model_new_cycle(model_ptr);
}
}
busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
ppc_regs[ppc_CRD].next = (model_reg *)0;
ppc_regs[ppc_CRD].in_use = 1;
busy_ptr->reg = &ppc_regs[ppc_CRD];
}
# Schedule an MFSPR instruction that takes 1 special purpose register and produces an integer output register
void::model-function::ppc_insn_from_spr:itable_index index, cpu *processor, model_data *model_ptr, signed_word *rD, unsigned nSPR
if (!WITH_MODEL_ISSUE)
return;
else {
registers *cpu_regs = cpu_registers(processor);
const unsigned ppc_RD = (rD - &cpu_regs->gpr[0]) + PPC_INT_REG;
const unsigned ppc_SPR = nSPR + PPC_SPR_REG;
model_reg *ppc_regs = model_ptr->registers;
model_busy *busy_ptr;
while (ppc_regs[ppc_SPR].in_use) {
model_ptr->nr_stalls_data++;
model_new_cycle(model_ptr);
}
busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
ppc_regs[ppc_RD].next = (model_reg *)0;
ppc_regs[ppc_RD].in_use = 1;
busy_ptr->reg = &ppc_regs[ppc_RD];
}
# Schedule an MTSPR instruction that takes 1 integer register and produces a special purpose output register
void::model-function::ppc_insn_to_spr:itable_index index, cpu *processor, model_data *model_ptr, unsigned nSPR, signed_word *rS
if (!WITH_MODEL_ISSUE)
return;
else {
registers *cpu_regs = cpu_registers(processor);
const unsigned ppc_RS = (rS - &cpu_regs->gpr[0]) + PPC_INT_REG;
const unsigned ppc_SPR = nSPR + PPC_SPR_REG;
model_reg *ppc_regs = model_ptr->registers;
model_busy *busy_ptr;
while (ppc_regs[ppc_RS].in_use) {
model_ptr->nr_stalls_data++;
model_new_cycle(model_ptr);
}
busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
ppc_regs[ppc_SPR].next = (model_reg *)0;
ppc_regs[ppc_SPR].in_use = 1;
busy_ptr->reg = &ppc_regs[ppc_SPR];
}
1995-11-17 20:17:58 +01:00
model_data *::model-function::model_create:cpu *processor
model_data *model_ptr = ZALLOC(model_data);
ASSERT(CURRENT_MODEL > 0 && CURRENT_MODEL < nr_models);
model_ptr->name = model_name[CURRENT_MODEL];
model_ptr->timing = model_time_mapping[CURRENT_MODEL];
model_ptr->processor = processor;
model_ptr->nr_cycles = 1;
return model_ptr;
1995-11-16 20:02:52 +01:00
1995-11-17 20:17:58 +01:00
void::model-function::model_init:model_data *model_ptr
1995-11-15 23:53:59 +01:00
1995-11-17 20:17:58 +01:00
void::model-function::model_halt:model_data *model_ptr
/* Let pipeline drain */
while (model_ptr->busy_list)
model_new_cycle(model_ptr);
1995-11-15 23:53:59 +01: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 20:02:52 +01:00
1995-11-15 23:53:59 +01:00
head = tail = ZALLOC(model_print);
1995-11-17 20:17:58 +01:00
tail->count = model_ptr->nr_cycles;
tail->name = "cycle";
tail->suffix_plural = "s";
1995-11-15 23:53:59 +01:00
tail->suffix_singular = "";
1995-11-16 20:02:52 +01:00
1995-11-18 02:14:45 +01:00
if (model_ptr->nr_stalls_data) {
tail->next = ZALLOC(model_print);
tail = tail->next;
tail->count = model_ptr->nr_stalls_data;
tail->name = "stall";
tail->suffix_plural = "s waiting for data";
tail->suffix_singular = " waiting for data";
}
if (model_ptr->nr_stalls_unit) {
tail->next = ZALLOC(model_print);
tail = tail->next;
tail->count = model_ptr->nr_stalls_unit;
tail->name = "stall";
tail->suffix_plural = "s waiting for a function unit";
tail->suffix_singular = " waiting for a function unit";
}
if (model_ptr->nr_stalls_serialize) {
tail->next = ZALLOC(model_print);
tail = tail->next;
tail->count = model_ptr->nr_stalls_serialize;
tail->name = "stall";
tail->suffix_plural = "s waiting for serialization";
tail->suffix_singular = " waiting for serialization";
}
if (model_ptr->nr_insns_not_handled) {
tail->next = ZALLOC(model_print);
tail = tail->next;
tail->count = model_ptr->nr_insns_not_handled;
tail->name = "instruction";
tail->suffix_plural = "s that were not accounted for in timing info";
tail->suffix_singular = " that was not accounted for in timing info";
}
1995-11-17 20:17:58 +01:00
if (model_ptr->nr_branches) {
tail->next = ZALLOC(model_print);
tail = tail->next;
tail->count = model_ptr->nr_branches;
tail->name = "branch";
tail->suffix_plural = "es";
tail->suffix_singular = "";
}
if (model_ptr->nr_branches_fallthrough) {
tail->next = ZALLOC(model_print);
tail = tail->next;
tail->count = model_ptr->nr_branches_fallthrough;
tail->name = "conditional branch";
tail->suffix_plural = "es fell through";
tail->suffix_singular = " fell through";
}
if (model_ptr->nr_branch_predict_trues) {
tail->next = ZALLOC(model_print);
tail = tail->next;
tail->count = model_ptr->nr_branch_predict_trues;
tail->name = "successful branch prediction";
tail->suffix_plural = "s";
tail->suffix_singular = "";
}
if (model_ptr->nr_branch_predict_falses) {
tail->next = ZALLOC(model_print);
tail = tail->next;
tail->count = model_ptr->nr_branch_predict_falses;
tail->name = "unsuccessful branch prediction";
tail->suffix_plural = "s";
tail->suffix_singular = "";
}
1995-11-16 20:02:52 +01:00
for (i = PPC_UNIT_BAD; i < nr_ppc_function_units; i++) {
1995-11-15 23:53:59 +01: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 20:02:52 +01:00
1995-11-15 23:53:59 +01:00
tail->next = (model_print *)0;
return head;
void::model-function::model_mon_info_free:model_data *model_ptr, model_print *ptr
while (ptr) {
1995-11-18 02:14:45 +01:00
model_print *next = ptr->next;
1995-11-15 23:53:59 +01:00
free((void *)ptr);
ptr = next;
}
void::model-function::model_branches:model_data *model_ptr, int failed
1995-11-18 02:14:45 +01:00
model_ptr->nr_units[PPC_UNIT_BPU]++;
model_ptr->insn_handled = 1;
if (failed)
model_ptr->nr_branches_fallthrough++;
else
model_ptr->nr_branches++;
1995-11-18 02:14:45 +01:00
model_new_cycle(model_ptr); /* A branch always ends the current cycle */
void::model-function::model_branch_predict:model_data *model_ptr, int success
if (success)
model_ptr->nr_branch_predict_trues++;
else
model_ptr->nr_branch_predict_falses++;
1995-11-01 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01: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-18 02:14:45 +01: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 20:32:38 +01:00
if (AA) NIA = IEA(EXTS(LI_0b00));
else NIA = IEA(CIA + EXTS(LI_0b00));
if (LK) LR = (spreg)CIA+4;
model_branches(cpu_model(processor), 1);
1995-11-01 20:32:38 +01:00
0.16,6.BO,11.BI,16.BD,30.AA,31.LK:B:t::Branch Conditional
1995-11-18 02:14:45 +01: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
int M, ctr_ok, cond_ok, succeed;
1995-11-18 02:14:45 +01:00
if (! BO{0})
model_wait_for_cr(cpu_model(processor), BIT32_BI);
1995-11-01 20:32:38 +01:00
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) {
1995-11-01 20:32:38 +01:00
if (AA) NIA = IEA(EXTS(BD_0b00));
else NIA = IEA(CIA + EXTS(BD_0b00));
succeed = 1;
}
else
succeed = 0;
1995-11-01 20:32:38 +01:00
if (LK) LR = (spreg)IEA(CIA + 4);
model_branches(cpu_model(processor), succeed);
if (! BO{0}) {
int reverse;
if (BO{4}) { /* branch prediction bit set, reverse sense of test */
reverse = EXTS(BD_0b00) < 0;
} else { /* branch prediction bit not set */
reverse = EXTS(BD_0b00) >= 0;
}
model_branch_predict(cpu_model(processor), reverse ? !succeed : succeed);
}
1995-11-01 20:32:38 +01:00
0.19,6.BO,11.BI,16./,21.16,31.LK:XL:t::Branch Conditional to Link Register
1995-11-18 02:14:45 +01: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
int M, ctr_ok, cond_ok, succeed;
1995-11-01 20:32:38 +01:00
if (is_64bit_implementation && is_64bit_mode) M = 0;
else M = 32;
1995-11-18 02:14:45 +01:00
if (! BO{0})
model_wait_for_cr(cpu_model(processor), BIT32_BI);
1995-11-01 20:32:38 +01:00
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);
succeed = 1;
}
else
succeed = 0;
1995-11-01 20:32:38 +01:00
if (LK) LR = (spreg)IEA(CIA + 4);
model_branches(cpu_model(processor), succeed);
if (! BO{0})
model_branch_predict(cpu_model(processor), BO{4} ? !succeed : succeed);
1995-11-01 20:32:38 +01:00
0.19,6.BO,11.BI,16./,21.528,31.LK:XL:t::Branch Conditional to Count Register
1995-11-18 02:14:45 +01: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
int cond_ok, succeed;
1995-11-18 02:14:45 +01:00
if (! BO{0})
model_wait_for_cr(cpu_model(processor), BIT32_BI);
1995-11-01 20:32:38 +01:00
cond_ok = BO{0} || (CR{BI} == BO{1});
if (cond_ok) {
NIA = IEA(CTR_0b00);
succeed = 1;
}
else
succeed = 0;
1995-11-01 20:32:38 +01:00
if (LK) LR = (spreg)IEA(CIA + 4);
model_branches(cpu_model(processor), succeed);
if (! BO{0})
model_branch_predict(cpu_model(processor), BO{4} ? !succeed : succeed);
1995-11-01 20:32:38 +01:00
#
# I.2.4.2 System Call Instruction
#
0.17,6./,11./,16./,30.1,31./:SC:t::System Call
1995-11-18 02:14:45 +01:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
*604: PPC_UNIT_SCIU1, PPC_UNIT_SCIU2, 1, 1, 0
model_serialize(my_index, cpu_model(processor));
1995-11-01 20:32:38 +01: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-18 02:14:45 +01: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 20:32:38 +01:00
BLIT32(CR, BT, CR{BA} && CR{BB});
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.19,6.BT,11.BA,16.BB,21.449,31./:XL::cror:Condition Register OR
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
BLIT32(CR, BT, CR{BA} || CR{BB});
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.19,6.BT,11.BA,16.BB,21.193,31./:XL::crxor:Condition Register XOR
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
BLIT32(CR, BT, CR{BA} != CR{BB});
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.19,6.BT,11.BA,16.BB,21.225,31./:XL::crnand:Condition Register NAND
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
BLIT32(CR, BT, !(CR{BA} && CR{BB}));
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.19,6.BT,11.BA,16.BB,21.33,31./:XL::crnor:Condition Register NOR
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
BLIT32(CR, BT, !(CR{BA} || CR{BB}));
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.19,6.BT,11.BA,16.BB,21.289,31./:XL::creqv:Condition Register Equivalent
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
BLIT32(CR, BT, CR{BA} == CR{BB});
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.19,6.BT,11.BA,16.BB,21.129,31./:XL::crandc:Condition Register AND with Complement
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
BLIT32(CR, BT, CR{BA} && !CR{BB});
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.19,6.BT,11.BA,16.BB,21.417,31./:XL::crorc:Condition Register OR with Complement
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
if (RA == 0)
ppc_insn_int0(my_index, processor, cpu_model(processor), rT, 0/*Rc*/);
else
ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16.RB,21.87,31./:X:::Load Byte and Zero Indexed
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
if (RA == 0)
ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rB, 0/*Rc*/);
else
ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, 0/*Rc*/);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.35,6.RT,11.RA,16.D:D:::Load Byte and Zero with Update
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
ppc_insn_int1_update(my_index, processor, cpu_model(processor), rT, rA);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16.RB,21.119,31./:X:::Load Byte and Zero with Update Indexed
1995-11-18 02:14:45 +01: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 20:32:38 +01: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;
1995-11-18 02:14:45 +01:00
ppc_insn_int2_update(my_index, processor, cpu_model(processor), rT, rA, rB);
1995-11-01 20:32:38 +01:00
0.40,6.RT,11.RA,16.D:D:::Load Halfword and Zero
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
if (RA == 0)
ppc_insn_int0(my_index, processor, cpu_model(processor), rT, 0/*Rc*/);
else
ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16.RB,21.279,31./:X:::Load Halfword and Zero Indexed
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + *rB;
*rT = MEM(unsigned, EA, 2);
1995-11-18 02:14:45 +01:00
if (RA == 0)
ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rB, 0/*Rc*/);
else
ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, 0/*Rc*/);
1995-11-01 20:32:38 +01:00
0.41,6.RT,11.RA,16.D:D:::Load Halfword and Zero with Update
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
ppc_insn_int1_update(my_index, processor, cpu_model(processor), rT, rA);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16.RB,21.311,31./:X:::Load Halfword and Zero with Update Indexed
1995-11-18 02:14:45 +01: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 20:32:38 +01: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;
1995-11-18 02:14:45 +01:00
ppc_insn_int2_update(my_index, processor, cpu_model(processor), rT, rA, rB);
1995-11-01 20:32:38 +01:00
0.42,6.RT,11.RA,16.D:D:::Load Halfword Algebraic
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
if (RA == 0)
ppc_insn_int0(my_index, processor, cpu_model(processor), rT, 0/*Rc*/);
else
ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16.RB,21.343,31./:X:::Load Halfword Algebraic Indexed
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
if (RA == 0)
ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rB, 0/*Rc*/);
else
ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, 0/*Rc*/);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.43,6.RT,11.RA,16.D:D:::Load Halfword Algebraic with Update
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
ppc_insn_int1_update(my_index, processor, cpu_model(processor), rT, rA);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16.RB,21.375,31./:X:::Load Halfword Algebraic with Update Indexed
1995-11-18 02:14:45 +01: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 20:32:38 +01: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;
1995-11-18 02:14:45 +01:00
ppc_insn_int2_update(my_index, processor, cpu_model(processor), rT, rA, rB);
1995-11-01 20:32:38 +01:00
0.32,6.RT,11.RA,16.D:D:::Load Word and Zero
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
if (RA == 0)
ppc_insn_int0(my_index, processor, cpu_model(processor), rT, 0/*Rc*/);
else
ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16.RB,21.23,31./:X:::Load Word and Zero Indexed
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
if (RA == 0)
ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rB, 0/*Rc*/);
else
ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, 0/*Rc*/);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.33,6.RT,11.RA,16.D:D:::Load Word and Zero with Update
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
ppc_insn_int1_update(my_index, processor, cpu_model(processor), rT, rA);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16.RB,21.55,31./:X:::Load Word and Zero with Update Indexed
1995-11-18 02:14:45 +01: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 20:32:38 +01: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;
1995-11-18 02:14:45 +01:00
ppc_insn_int2_update(my_index, processor, cpu_model(processor), rT, rA, rB);
1995-11-01 20:32:38 +01:00
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 20:02:52 +01:00
1995-11-01 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01: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-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
if (RA == 0)
ppc_insn_int0_noout(my_index, processor, cpu_model(processor));
else
ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rA);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16.RB,21.215,31./:X:::Store Byte Indexed
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + *rB;
STORE(EA, 1, *rS);
1995-11-18 02:14:45 +01:00
if (RA == 0)
ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
else
ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.39,6.RS,11.RA,16.D:D:::Store Byte with Update
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rA, 0/*Rc*/);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16.RB,21.247,31./:X:::Store Byte with Update Indexed
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
unsigned_word EA;
if (RA == 0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + *rB;
STORE(EA, 1, *rS);
*rA = EA;
1995-11-18 02:14:45 +01:00
ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rA, rB, 0/*Rc*/);
1995-11-01 20:32:38 +01:00
0.44,6.RS,11.RA,16.D:D:::Store Half Word
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
if (RA == 0)
ppc_insn_int0_noout(my_index, processor, cpu_model(processor));
else
ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rA);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16.RB,21.407,31./:X:::Store Half Word Indexed
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + *rB;
STORE(EA, 2, *rS);
1995-11-18 02:14:45 +01:00
if (RA == 0)
ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
else
ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.45,6.RS,11.RA,16.D:D:::Store Half Word with Update
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rA, 0/*Rc*/);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16.RB,21.439,31./:X:::Store Half Word with Update Indexed
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
unsigned_word EA;
if (RA == 0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + *rB;
STORE(EA, 2, *rS);
*rA = EA;
1995-11-18 02:14:45 +01:00
ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rA, rB, 0/*Rc*/);
1995-11-01 20:32:38 +01:00
0.36,6.RS,11.RA,16.D:D:::Store Word
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
if (RA == 0)
ppc_insn_int0_noout(my_index, processor, cpu_model(processor));
else
ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rA);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16.RB,21.151,31./:X:::Store Word Indexed
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
unsigned_word b;
unsigned_word EA;
if (RA == 0) b = 0;
else b = *rA;
EA = b + *rB;
STORE(EA, 4, *rS);
1995-11-18 02:14:45 +01:00
if (RA == 0)
ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
else
ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.37,6.RS,11.RA,16.D:D:::Store Word with Update
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rA, 0/*Rc*/);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16.RB,21.183,31./:X:::Store Word with Update Indexed
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
unsigned_word EA;
if (RA == 0)
program_interrupt(processor, cia,
illegal_instruction_program_interrupt);
EA = *rA + *rB;
STORE(EA, 4, *rS);
*rA = EA;
1995-11-18 02:14:45 +01:00
ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rA, rB, 0/*Rc*/);
1995-11-01 20:32:38 +01:00
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-18 02:14:45 +01: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
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-18 02:14:45 +01:00
if (RA == 0)
ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rB, 0/*Rc*/);
else
ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, 0/*Rc*/);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16.RB,21.534,31./:X:::Load Word Byte-Reverse Indexed
1995-11-18 02:14:45 +01: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
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-18 02:14:45 +01:00
if (RA == 0)
ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rB, 0/*Rc*/);
else
ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, 0/*Rc*/);
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16.RB,21.918,31./:X:::Store Half Word Byte-Reversed Indexed
1995-11-18 02:14:45 +01: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
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-18 02:14:45 +01:00
if (RA == 0)
ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
else
ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16.RB,21.662,31./:X:::Store Word Byte-Reversed Indexed
1995-11-18 02:14:45 +01: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
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-18 02:14:45 +01:00
if (RA == 0)
ppc_insn_int1_noout(my_index, processor, cpu_model(processor), rB);
else
ppc_insn_int2_noout(my_index, processor, cpu_model(processor), rA, rB);
1995-11-01 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01: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-18 02:14:45 +01: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, 0
1995-11-01 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01: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-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01: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_LSU, PPC_UNIT_LSU, 1, 1, 0
1995-11-01 20:32:38 +01: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-18 02:14:45 +01: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
if (RA_is_0) {
*rT = EXTS(SI);
ppc_insn_int0(my_index, processor, cpu_model(processor), rT, 0/*Rc*/);
}
else {
*rT = *rA + EXTS(SI);
ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
}
1995-11-15 23:53:59 +01:00
1995-11-01 20:32:38 +01:00
0.15,6.RT,11.RA,16.SI:D:::Add Immediate Shifted
1995-11-18 02:14:45 +01: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
if (RA_is_0) {
*rT = EXTS(SI) << 16;
ppc_insn_int0(my_index, processor, cpu_model(processor), rT, 0/*Rc*/);
}
else {
*rT = *rA + (EXTS(SI) << 16);
ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
}
1995-11-15 23:53:59 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16.RB,21.OE,22.266,31.Rc:XO:::Add
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
ALU_BEGIN(*rA);
ALU_ADD(*rB);
ALU_END(*rT, 0/*CA*/, OE, Rc);
1995-11-18 02:14:45 +01:00
ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
1995-11-15 23:53:59 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16.RB,21.OE,22.40,31.Rc:XO:::Subtract From
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
ALU_BEGIN(*rA);
ALU_NOT;
ALU_ADD(*rB);
ALU_ADD(1);
ALU_END(*rT, 0/*CA*/, OE, Rc);
1995-11-18 02:14:45 +01:00
ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
1995-11-15 23:53:59 +01:00
1995-11-01 20:32:38 +01:00
0.12,6.RT,11.RA,16.SI:D:::Add Immediate Carrying
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
ALU_BEGIN(*rA);
ALU_ADD(EXTS(SI));
ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
1995-11-18 02:14:45 +01:00
ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
1995-11-15 23:53:59 +01:00
1995-11-01 20:32:38 +01:00
0.13,6.RT,11.RA,16.SI:D:::Add Immediate Carrying and Record
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
ALU_BEGIN(*rA);
ALU_ADD(EXTS(SI));
ALU_END(*rT, 1/*CA*/, 0/*OE*/, 1/*Rc*/);
1995-11-18 02:14:45 +01:00
ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 1/*Rc*/);
1995-11-15 23:53:59 +01:00
1995-11-01 20:32:38 +01:00
0.8,6.RT,11.RA,16.SI:D:::Subtract From Immediate Carrying
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
ALU_BEGIN(*rA);
ALU_NOT;
ALU_ADD(EXTS(SI));
ALU_ADD(1);
ALU_END(*rT, 1/*CA*/, 0/*OE*/, 0/*Rc*/);
1995-11-18 02:14:45 +01:00
ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
1995-11-15 23:53:59 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16.RB,21.OE,22.10,31.Rc:XO:::Add Carrying
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
ALU_BEGIN(*rA);
ALU_ADD(*rB);
ALU_END(*rT, 1/*CA*/, OE, Rc);
1995-11-18 02:14:45 +01:00
ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
1995-11-15 23:53:59 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16.RB,21.OE,22.8,31.Rc:XO:::Subtract From Carrying
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
1995-11-15 23:53:59 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16.RB,21.OE,22.138,31.Rc:XO:::Add Extended
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
ALU_BEGIN(*rA);
ALU_ADD(*rB);
ALU_ADD_CA;
ALU_END(*rT, 1/*CA*/, OE, Rc);
1995-11-18 02:14:45 +01:00
ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
1995-11-15 23:53:59 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16.RB,21.OE,22.136,31.Rc:XO:::Subtract From Extended
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
ALU_BEGIN(*rA);
ALU_NOT;
ALU_ADD(*rB);
ALU_ADD_CA;
ALU_END(*rT, 1/*CA*/, OE, Rc);
1995-11-18 02:14:45 +01:00
ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
1995-11-15 23:53:59 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16./,21.OE,22.234,31.Rc:XO:::Add to Minus One Extended
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
# ALU_BEGIN(*rA);
# ALU_ADD_CA;
# ALU_SUB(1);
# ALU_END(*rT, 1/*CA*/, OE, Rc);
1995-11-15 23:53:59 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16./,21.OE,22.232,31.Rc:XO:::Subtract From Minus One Extended
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
# ALU_BEGIN(*rA);
# ALU_NOT;
# ALU_ADD_CA;
# ALU_SUB(1);
# ALU_END(*rT, 1/*CA*/, OE, Rc);
1995-11-15 23:53:59 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16./,21.OE,22.202,31.Rc:XO::addze:Add to Zero Extended
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
ALU_BEGIN(*rA);
ALU_ADD_CA;
ALU_END(*rT, 1/*CA*/, OE, Rc);
1995-11-18 02:14:45 +01:00
ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, Rc);
1995-11-15 23:53:59 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16./,21.OE,22.200,31.Rc:XO:::Subtract from Zero Extended
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
ALU_BEGIN(*rA);
ALU_NOT;
ALU_ADD_CA;
ALU_END(*rT, 1/*CA*/, OE, Rc);
1995-11-18 02:14:45 +01:00
ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, Rc);
1995-11-15 23:53:59 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16./,21.OE,22.104,31.Rc:XO:::Negate
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
ALU_BEGIN(*rA);
ALU_NOT;
ALU_ADD(1);
ALU_END(*rT,0/*CA*/,OE,Rc);
1995-11-18 02:14:45 +01:00
ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, Rc);
1995-11-15 23:53:59 +01:00
1995-11-01 20:32:38 +01:00
0.7,6.RT,11.RA,16.SI:D::mulli:Multiply Low Immediate
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
signed_word prod = *rA * EXTS(SI);
*rT = prod;
1995-11-18 02:14:45 +01:00
ppc_insn_int1(my_index, processor, cpu_model(processor), rT, rA, 0/*Rc*/);
1995-11-15 23:53:59 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16.RB,21.OE,22.233,31.Rc:D:64::Multiply Low Doubleword
1995-11-15 23:53:59 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16.RB,21.OE,22.235,31.Rc:XO::mullw:Multiply Low Word
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
1995-11-15 23:53:59 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16.RB,21./,22.73,31.Rc:XO:64::Multiply High Doubleword
1995-11-15 23:53:59 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16.RB,21./,22.75,31.Rc:XO::mulhw:Multiply High Word
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
1995-11-15 23:53:59 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16.RB,21./,22.9,31.Rc:XO:64::Multiply High Doubleword Unsigned
1995-11-15 23:53:59 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16.RB,21./,22.11,31.Rc:XO::milhwu:Multiply High Word Unsigned
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
1995-11-15 23:53:59 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16.RB,21.OE,22.489,31.Rc:XO:64::Divide Doubleword
1995-11-15 23:53:59 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16.RB,21.OE,22.491,31.Rc:XO::divw:Divide Word
1995-11-18 02:14:45 +01: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 20:32:38 +01: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);
}
1995-11-18 02:14:45 +01:00
ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16.RB,21.OE,22.457,31.Rc:XO:64::Divide Doubleword Unsigned
1995-11-15 23:53:59 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11.RA,16.RB,21.OE,22.459,31.Rc:XO::divwu:Divide Word Unsigned
1995-11-18 02:14:45 +01: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 20:32:38 +01: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);
}
1995-11-18 02:14:45 +01:00
ppc_insn_int2(my_index, processor, cpu_model(processor), rT, rA, rB, Rc);
1995-11-01 20:32:38 +01:00
#
# I.3.3.10 Fixed-Point Compare Instructions
#
0.11,6.BF,9./,10.L,11.RA,16.SI:D:::Compare Immediate
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
ppc_insn_int1_cr(my_index, processor, cpu_model(processor), BF, rA);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.BF,9./,10.L,11.RA,16.RB,21.0,31./:X:::Compare
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
ppc_insn_int2_cr(my_index, processor, cpu_model(processor), BF, rA, rB);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.10,6.BF,9./,10.L,11.RA,16.UI:D:::Compare Logical Immediate
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
ppc_insn_int1_cr(my_index, processor, cpu_model(processor), BF, rA);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.BF,9./,10.L,11.RA,16.RB,21.32,31./:X:::Compare Logical
1995-11-18 02:14:45 +01: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 20:32:38 +01: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);
}
1995-11-18 02:14:45 +01:00
ppc_insn_int2_cr(my_index, processor, cpu_model(processor), BF, rA, rB);
1995-11-01 20:32:38 +01:00
#
# 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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.3,6.TO,11.RA,16.SI:D:::Trap Word Immediate
1995-11-18 02:14:45 +01: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 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.TO,11.RA,16.RB,21.4,31./:X:::Trap Word
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01: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 20:32:38 +01:00
*rA = *rS & UI;
CR0_COMPARE(*rA, 0, 1/*Rc*/);
1995-11-18 02:14:45 +01:00
ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, 1/*Rc*/);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.29,6.RS,11.RA,16.UI:D:::AND Immediate Shifted
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
*rA = *rS & (UI << 16);
CR0_COMPARE(*rA, 0, 1/*Rc*/);
1995-11-18 02:14:45 +01:00
ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, 1/*Rc*/);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.24,6.RS,11.RA,16.UI:D:::OR Immediate
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
*rA = *rS | UI;
1995-11-18 02:14:45 +01:00
ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, 0);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.25,6.RS,11.RA,16.UI:D:::OR Immediate Shifted
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
*rA = *rS | (UI << 16);
1995-11-18 02:14:45 +01:00
ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, 0);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.26,6.RS,11.RA,16.UI:D:::XOR Immediate
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
*rA = *rS ^ UI;
1995-11-18 02:14:45 +01:00
ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, 0);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.27,6.RS,11.RA,16.UI:D:::XOR Immediate Shifted
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
*rA = *rS ^ (UI << 16);
1995-11-18 02:14:45 +01:00
ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, 0);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16.RB,21.28,31.Rc:X:::AND
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
*rA = *rS & *rB;
CR0_COMPARE(*rA, 0, Rc);
1995-11-18 02:14:45 +01:00
ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16.RB,21.444,31.Rc:X:::OR
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
*rA = *rS | *rB;
CR0_COMPARE(*rA, 0, Rc);
1995-11-18 02:14:45 +01:00
ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16.RB,21.316,31.Rc:X:::XOR
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
*rA = *rS ^ *rB;
CR0_COMPARE(*rA, 0, Rc);
1995-11-18 02:14:45 +01:00
ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16.RB,21.476,31.Rc:X:::NAND
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
*rA = ~(*rS & *rB);
CR0_COMPARE(*rA, 0, Rc);
1995-11-18 02:14:45 +01:00
ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16.RB,21.124,31.Rc:X:::NOR
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
*rA = ~(*rS | *rB);
CR0_COMPARE(*rA, 0, Rc);
1995-11-18 02:14:45 +01:00
ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16.RB,21.284,31.Rc:X:::Equivalent
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
# *rA = ~(*rS ^ *rB); /* A === B */
# CR0_COMPARE(*rA, 0, Rc);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16.RB,21.60,31.Rc:X:::AND with Complement
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
*rA = *rS & ~*rB;
CR0_COMPARE(*rA, 0, Rc);
1995-11-18 02:14:45 +01:00
ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16.RB,21.412,31.Rc:X:::OR with Complement
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
*rA = *rS | ~*rB;
CR0_COMPARE(*rA, 0, Rc);
1995-11-18 02:14:45 +01:00
ppc_insn_int2(my_index, processor, cpu_model(processor), rA, rS, rB, Rc);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16./,21.954,31.Rc:X::extsb:Extend Sign Byte
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
*rA = (signed_word)(signed8)*rS;
CR0_COMPARE(*rA, 0, Rc);
1995-11-18 02:14:45 +01:00
ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16./,21.922,31.Rc:X::extsh:Extend Sign Half Word
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
*rA = (signed_word)(signed16)*rS;
CR0_COMPARE(*rA, 0, Rc);
1995-11-18 02:14:45 +01:00
ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16./,21.986,31.Rc:X:64::Extend Sign Word
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
# *rA = (signed_word)(signed32)*rS;
# CR0_COMPARE(*rA, 0, Rc);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16./,21.26,31.Rc:X:::Count Leading Zeros Word
1995-11-18 02:14:45 +01: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 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01: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-18 02:14:45 +01: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 20:32:38 +01: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));
1995-11-18 02:14:45 +01:00
ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
1995-11-01 20:32:38 +01:00
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 20:02:52 +01:00
1995-11-01 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01: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-18 02:14:45 +01: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 20:32:38 +01: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);
1995-11-18 02:14:45 +01:00
ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16.RB,21.27,31.Rc:X:64::Shift Left Doubleword
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16.RB,21.24,31.Rc:X:::Shift Left Word
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16.RB,21.539,31.Rc:X:64::Shift Right Doubleword
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16.RB,21.536,31.Rc:X:::Shift Right Word
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
1995-11-01 20:32:38 +01:00
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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16.SH,21.824,31.Rc:X:::Shift Right Algebraic Word Immediate
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16.RB,21.794,31.Rc:X:64::Shift Right Algebraic Doubleword
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16.RB,21.792,31.Rc:X:::Shift Right Algebraic Word
1995-11-18 02:14:45 +01: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 20:32:38 +01: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);
1995-11-18 02:14:45 +01:00
ppc_insn_int1(my_index, processor, cpu_model(processor), rA, rS, Rc);
1995-11-01 20:32:38 +01:00
#
# I.3.3.14 Move to/from System Register Instructions
#
1995-11-15 23:53:59 +01:00
0.31,6.RS,11.spr,21.467,31./:XFX::mtspr %SPR, %RS:Move to Special Purpose Register
1995-11-18 02:14:45 +01: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 20:32:38 +01: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 23:53:59 +01:00
(MASKED64(cpu_get_time_base(processor), 32, 63)
| INSERTED64(new_val, 0, 31)));
1995-11-01 20:32:38 +01:00
break;
case spr_tbl:
cpu_set_time_base(processor,
1995-11-15 23:53:59 +01:00
(MASKED64(cpu_get_time_base(processor), 0, 31)
| INSERTED64(new_val, 32, 63)));
1995-11-01 20:32:38 +01: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-18 02:14:45 +01:00
ppc_insn_to_spr(my_index, processor, cpu_model(processor), n, rS);
1995-11-16 20:02:52 +01:00
1995-11-15 23:53:59 +01:00
0.31,6.RT,11.spr,21.339,31./:XFX::mfspr %RT, %SPR:Move from Special Purpose Register
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
ppc_insn_from_spr(my_index, processor, cpu_model(processor), rT, n);
1995-11-16 20:02:52 +01:00
# FIXME: 604 uses SCIU{1,2} if only one bit is being set
1995-11-01 20:32:38 +01:00
0.31,6.RS,11./,12.FXM,20./,21.144,31./:XFX::mtfcr:Move to Condition Register Fields
1995-11-18 02:14:45 +01: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 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.BF,9./,11./,16./,21.512,31./:X:::Move to Condition Register from XER
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11./,16./,21.19,31./:X:::Move From Condition Register
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01: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 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.FRT,11.RA,16.RB,21.535,31./:X:f::Load Floating-Point Single Indexed
1995-11-18 02:14:45 +01: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 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.49,6.FRT,11.RA,16.D:D:f::Load Floating-Point Single with Update
1995-11-18 02:14:45 +01: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 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.FRT,11.RA,16.RB,21.576,31./:X:f::Load Floating-Point Single with Update Indexed
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01: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 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.FRT,11.RA,16.RB,21.599,31./:X:f::Load Floating-Point Double Indexed
1995-11-18 02:14:45 +01: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 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.51,6.FRT,11.RA,16.D:D:f::Load Floating-Point Double with Update
1995-11-18 02:14:45 +01: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 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.FRT,11.RA,16.RB,21.631,31./:X:f::Load Floating-Point Double with Update Indexed
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01: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 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.FRS,11.RA,16.RB,21.663,31./:X:f::Store Floating-Point Single Indexed
1995-11-18 02:14:45 +01: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 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.53,6.FRS,11.RA,16.D:D:f::Store Floating-Point Single with Update
1995-11-18 02:14:45 +01: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 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.FRS,11.RA,16.RB,21.695,31./:X:f::Store Floating-Point Single with Update Indexed
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01: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 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.FRS,11.RA,16.RB,21.727,31./:X:f::Store Floating-Point Double Indexed
1995-11-18 02:14:45 +01: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 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.55,6.FRS,11.RA,16.D:D:f::Store Floating-Point Double with Update
1995-11-18 02:14:45 +01: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 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.FRS,11.RA,16.RB,21.759,31./:X:f::Store Floating-Point Double with Update Indexed
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01: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 20:32:38 +01:00
*frT = *frB;
CR1_UPDATE(Rc);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.63,6.FRT,11./,16.FRB,21.40,31.Rc:X:f::Floating Negate
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
*frT = *frB ^ BIT64(0);
CR1_UPDATE(Rc);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.63,6.FRT,11./,16.FRB,21.264,31.Rc:X:f::Floating Absolute Value
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
*frT = *frB & ~BIT64(0);
CR1_UPDATE(Rc);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.63,6.FRT,11./,16.FRB,21.136,31.Rc:X:f::Floating Negative Absolute Value
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01: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 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.59,6.FRT,11.FRA,16.FRB,21./,26.21,31.Rc:A:f:fadds:Floating Add Single
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01: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 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.59,6.FRT,11.FRA,16.FRB,21./,26.20,31.Rc:A:f:fsubs:Floating Subtract Single
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01: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 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.59,6.FRT,11.FRA,16./,21.FRC,26.25,31.Rc:A:f:fmuls:Floating Multiply Single
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01: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 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.59,6.FRT,11.FRA,16.FRB,21./,26.18,31.Rc:A:f:fdivs:Floating Divide Single
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01: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 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.29,31.Rc:A:f::Floating Multiply-Add Single
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract
1995-11-18 02:14:45 +01: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-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.28,31.Rc:A:f::Floating Multiply-Subtract Single
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add
1995-11-18 02:14:45 +01: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-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.31,31.Rc:A:f::Floating Negative Multiply-Add Single
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
0.63,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract
1995-11-18 02:14:45 +01: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-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.59,6.FRT,11.FRA,16.FRB,21.FRC,26.30,31.Rc:A:f::Floating Negative Multiply-Subtract Single
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01: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 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.63,6.FRT,11./,16.FRB,21.814,31.Rc:X:64,f::Floating Convert To Integer Doubleword
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.63,6.FRT,11./,16.FRB,21.14,31.Rc:X:f::Floating Convert To Integer Word
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01: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-18 02:14:45 +01: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 20:32:38 +01:00
FPSCR_BEGIN;
convert_to_integer(processor, cia,
frT, *frB,
fpscr_rn_round_towards_zero, 32);
FPSCR_END(Rc);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01: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-18 02:14:45 +01: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 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.63,6.BF,9./,11.FRA,16.FRB,21.32,31./:X:f:fcmpo:Floating Compare Ordered
1995-11-18 02:14:45 +01: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 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.63,6.BF,9./,11.BFA,14./,16./,21.64,31./:X:f::Move to Condition Register from FPSCR
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.64,6.BF,9./,11./,16.U,20./,21.134,31.Rc:X:f::Move To FPSCR Field Immediate
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.63,6./,7.FLM,15./,16.FRB,21.711,31.Rc:XFL:f::Move To FPSCR Fields
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.63,6.BT,11./,16./,21.70,31.Rc:X:f::Move To FPSCR Bit 0
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01: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-18 02:14:45 +01:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
1995-11-15 23:53:59 +01:00
/* blindly flush all instruction cache entries */
#if WITH_IDECODE_CACHE_SIZE
cpu_flush_icache(processor);
#endif
1995-11-01 20:32:38 +01:00
0.19,6./,11./,16./,21.150,31./:XL::isync:Instruction Synchronize
1995-11-18 02:14:45 +01:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
1995-11-01 20:32:38 +01: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-18 02:14:45 +01:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*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, 0
1995-11-16 20:02:52 +01:00
TRACE(trace_tbd,("Data Cache Block Touch\n"));
1995-11-01 20:32:38 +01:00
0.31,6./,11.RA,16.RB,21.246,31./:X:::Data Cache Block Touch for Store
1995-11-18 02:14:45 +01:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*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, 0
1995-11-16 20:02:52 +01:00
TRACE(trace_tbd,("Data Cache Block Touch for Store\n"));
1995-11-01 20:32:38 +01:00
0.31,6./,11.RA,16.RB,21.1014,31./:X:::Data Cache Block set to Zero
1995-11-18 02:14:45 +01:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 10, 10, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 10, 10, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 3, 0
1995-11-16 20:02:52 +01:00
TRACE(trace_tbd,("Data Cache Block set to Zero\n"));
1995-11-01 20:32:38 +01:00
0.31,6./,11.RA,16.RB,21.54,31./:X:::Data Cache Block Store
1995-11-18 02:14:45 +01:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
1995-11-16 20:02:52 +01:00
TRACE(trace_tbd,("Data Cache Block Store\n"));
1995-11-01 20:32:38 +01:00
0.31,6./,11.RA,16.RB,21.86,31./:X:::Data Cache Block Flush
1995-11-18 02:14:45 +01:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
*603e:PPC_UNIT_LSU, PPC_UNIT_LSU, 5, 5, 0
*604: PPC_UNIT_LSU, PPC_UNIT_LSU, 1, 1, 0
1995-11-16 20:02:52 +01:00
TRACE(trace_tbd,("Data Cache Block Flush\n"));
1995-11-01 20:32:38 +01:00
#
1995-11-16 20:02:52 +01:00
# II.3.3 Enforce In-order Execution of I/O Instruction
1995-11-01 20:32:38 +01: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-18 02:14:45 +01: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 20:32:38 +01: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 23:53:59 +01:00
0.19,6./,11./,16./,21.50,31./:XL::rfi:Return From Interrupt
1995-11-18 02:14:45 +01:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 3, 3, 0
1995-11-15 23:53:59 +01: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 20:32:38 +01: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-18 02:14:45 +01: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 20:32:38 +01:00
if (IS_PROBLEM_STATE(processor))
program_interrupt(processor, cia,
privileged_instruction_program_interrupt);
else
MSR = *rS;
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11./,16./,21.83,31./:X:::Move From Machine State Register
1995-11-18 02:14:45 +01: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 20:32:38 +01: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-18 02:14:45 +01:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
*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, 0
1995-11-16 20:02:52 +01:00
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 20:32:38 +01: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-18 02:14:45 +01: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 20:32:38 +01:00
if (IS_PROBLEM_STATE(processor))
program_interrupt(processor, cia,
privileged_instruction_program_interrupt);
else
SEGREG(SR) = *rS;
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11./,16.RB,21.242,31./:X:32:mtsrin %RS,%RB:Move To Segment Register Indirect
1995-11-18 02:14:45 +01: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 20:32:38 +01:00
if (IS_PROBLEM_STATE(processor))
program_interrupt(processor, cia,
privileged_instruction_program_interrupt);
else
SEGREG(EXTRACTED32(*rB, 0, 3)) = *rS;
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11./,12.SR,16./,21.595,31./:X:32:mfsr %RT,%RS:Move From Segment Register
1995-11-18 02:14:45 +01:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
1995-11-01 20:32:38 +01:00
if (IS_PROBLEM_STATE(processor))
program_interrupt(processor, cia,
privileged_instruction_program_interrupt);
else
*rT = SEGREG(SR);
1995-11-16 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RT,11./,16.RB,21.659,31./:X:32:mfsrin %RT,%RB:Move From Segment Register Indirect
1995-11-18 02:14:45 +01:00
*601: PPC_UNIT_IU, PPC_UNIT_IU, 2, 2, 0
*603: PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 3, 3, 0
*604: PPC_UNIT_MCIU, PPC_UNIT_MCIU, 1, 1, 0
1995-11-01 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01: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 20:02:52 +01:00
1995-11-01 20:32:38 +01:00
0.31,6.RS,11.RA,16.RB,21.438,31./:X:earwax::External Control Out Word Indexed