📄 e500.igen
字号:
# e500 core instructions, for PSIM, the PowerPC simulator.# Copyright 2003 Free Software Foundation, Inc.# Contributed by Red Hat Inc; developed under contract from Motorola.# Written by matthew green <mrg@redhat.com>.# This file is part of GDB.# 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, 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; see the file COPYING. If not, write to# the Free Software Foundation, 59 Temple Place - Suite 330,# Boston, MA 02111-1307, USA.## e500 Core Complex Instructions#:cache:e500::signed_word *:rAh:RA:(cpu_registers(processor)->e500.gprh + RA):cache:e500::signed_word *:rSh:RS:(cpu_registers(processor)->e500.gprh + RS):cache:e500::signed_word *:rBh:RB:(cpu_registers(processor)->e500.gprh + RB)# Flags for model.h::model-macro::: #define PPC_INSN_INT_SPR(OUT_MASK, IN_MASK, SPR) \ do { \ if (CURRENT_MODEL_ISSUE > 0) \ ppc_insn_int_spr(MY_INDEX, cpu_model(processor), OUT_MASK, IN_MASK, SPR); \ } while (0)# Schedule an instruction that takes 2 integer register and produces a special purpose output register plus an integer output registervoid::model-function::ppc_insn_int_spr:itable_index index, model_data *model_ptr, const unsigned32 out_mask, const unsigned32 in_mask, const unsigned nSPR const unsigned32 int_mask = out_mask | in_mask; model_busy *busy_ptr; while ((model_ptr->int_busy & int_mask) != 0 || model_ptr->spr_busy[nSPR] != 0) { if (WITH_TRACE && ppc_trace[trace_model]) model_trace_busy_p(model_ptr, int_mask, 0, 0, nSPR); model_ptr->nr_stalls_data++; model_new_cycle(model_ptr); } busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]); busy_ptr->int_busy |= out_mask; model_ptr->int_busy |= out_mask; busy_ptr->spr_busy = nSPR; model_ptr->spr_busy[nSPR] = 1; busy_ptr->nr_writebacks = (PPC_ONE_BIT_SET_P(out_mask)) ? 3 : 2; TRACE(trace_model,("Making register %s busy.\n", spr_name(nSPR)));## SPE Modulo Fractional Multiplication handling support#:function:e500::unsigned64:ev_multiply16_smf:signed16 a, signed16 b, int *sat signed32 a32 = a, b32 = b, rv32; rv32 = a * b; *sat = (rv32 & (3<<30)) == (3<<30); return (signed64)rv32 << 1;:function:e500::unsigned64:ev_multiply32_smf:signed32 a, signed32 b, int *sat signed64 rv64, a64 = a, b64 = b; rv64 = a64 * b64; *sat = (rv64 & ((signed64)3<<62)) == ((signed64)3<<62); /* Loses top sign bit. */ return rv64 << 1;## SPE Saturation handling support#:function:e500::signed32:ev_multiply16_ssf:signed16 a, signed16 b, int *sat signed32 rv32; if (a == 0xffff8000 && b == 0xffff8000) { rv32 = 0x7fffffffL; * sat = 1; return rv32; } else { signed32 a32 = a, b32 = b; rv32 = a * b; * sat = (rv32 & (3<<30)) == (3<<30); return (signed64)rv32 << 1; }:function:e500::signed64:ev_multiply32_ssf:signed32 a, signed32 b, int *sat signed64 rv64; if (a == 0x80000000 && b == 0x80000000) { rv64 = 0x7fffffffffffffffLL; * sat = 1; return rv64; } else { signed64 a64 = a, b64 = b; rv64 = a64 * b64; *sat = (rv64 & ((signed64)3<<62)) == ((signed64)3<<62); /* Loses top sign bit. */ return rv64 << 1; }## SPE FP handling support#:function:e500::void:ev_check_guard:sim_fpu *a, int fg, int fx, cpu *processor unsigned64 guard; guard = sim_fpu_guard(a, 0); if (guard & 1) EV_SET_SPEFSCR_BITS(fg); if (guard & ~1) EV_SET_SPEFSCR_BITS(fx);:function:e500::void:booke_sim_fpu_32to:sim_fpu *dst, unsigned32 packed sim_fpu_32to (dst, packed); /* Set normally unused fields to allow booke arithmetic. */ if (dst->class == sim_fpu_class_infinity) { dst->normal_exp = 128; dst->fraction = ((unsigned64)1 << 60); } else if (dst->class == sim_fpu_class_qnan || dst->class == sim_fpu_class_snan) { dst->normal_exp = 128; /* This is set, but without the implicit bit, so we have to or in the implicit bit. */ dst->fraction |= ((unsigned64)1 << 60); }:function:e500::int:booke_sim_fpu_add:sim_fpu *d, sim_fpu *a, sim_fpu *b, int inv, int over, int under, cpu *processor int invalid_operand, overflow_result, underflow_result; int dest_exp; invalid_operand = 0; overflow_result = 0; underflow_result = 0; /* Treat NaN, Inf, and denorm like normal numbers, and signal invalid operand if it hasn't already been done. */ if (EV_IS_INFDENORMNAN (a)) { a->class = sim_fpu_class_number; EV_SET_SPEFSCR_BITS (inv); invalid_operand = 1; } if (EV_IS_INFDENORMNAN (b)) { b->class = sim_fpu_class_number; if (! invalid_operand) { EV_SET_SPEFSCR_BITS (inv); invalid_operand = 1; } } sim_fpu_add (d, a, b); dest_exp = booke_sim_fpu_exp (d); /* If this is a denorm, force to zero, and signal underflow if we haven't already indicated invalid operand. */ if (dest_exp <= -127) { int sign = d->sign; *d = sim_fpu_zero; d->sign = sign; if (! invalid_operand) { EV_SET_SPEFSCR_BITS (under); underflow_result = 1; } } /* If this is Inf/NaN, force to pmax/nmax, and signal overflow if we haven't already indicated invalid operand. */ else if (dest_exp >= 127) { int sign = d->sign; *d = sim_fpu_max32; d->sign = sign; if (! invalid_operand) { EV_SET_SPEFSCR_BITS (over); overflow_result = 1; } } /* Destination sign is sign of operand with larger magnitude, or the sign of the first operand if operands have the same magnitude. Thus if the result is zero, we force it to have the sign of the first operand. */ else if (d->fraction == 0) d->sign = a->sign; return invalid_operand || overflow_result || underflow_result;:function:e500::unsigned32:ev_fs_add:unsigned32 aa, unsigned32 bb, int inv, int over, int under, int fg, int fx, cpu *processor sim_fpu a, b, d; unsigned32 w; int exception; booke_sim_fpu_32to (&a, aa); booke_sim_fpu_32to (&b, bb); exception = booke_sim_fpu_add (&d, &a, &b, inv, over, under, processor); sim_fpu_to32 (&w, &d); if (! exception) ev_check_guard(&d, fg, fx, processor); return w;:function:e500::unsigned32:ev_fs_sub:unsigned32 aa, unsigned32 bb, int inv, int over, int under, int fg, int fx, cpu *processor sim_fpu a, b, d; unsigned32 w; int exception; booke_sim_fpu_32to (&a, aa); booke_sim_fpu_32to (&b, bb); /* Invert sign of second operand, and add. */ b.sign = ! b.sign; exception = booke_sim_fpu_add (&d, &a, &b, inv, over, under, processor); sim_fpu_to32 (&w, &d); if (! exception) ev_check_guard(&d, fg, fx, processor); return w;# sim_fpu_exp leaves the normal_exp field undefined for Inf and NaN.# The booke algorithms require exp values, so we fake them here.# fixme: It also apparently does the same for zero, but should not.:function:e500::unsigned32:booke_sim_fpu_exp:sim_fpu *x int y = sim_fpu_is (x); if (y == SIM_FPU_IS_PZERO || y == SIM_FPU_IS_NZERO) return 0; else if (y == SIM_FPU_IS_SNAN || y == SIM_FPU_IS_QNAN || y == SIM_FPU_IS_NINF || y == SIM_FPU_IS_PINF) return 128; else return sim_fpu_exp (x);:function:e500::unsigned32:ev_fs_mul:unsigned32 aa, unsigned32 bb, int inv, int over, int under, int fg, int fx, cpu *processor sim_fpu a, b, d; unsigned32 w; int sa, sb, ea, eb, ei; sim_fpu_32to (&a, aa); sim_fpu_32to (&b, bb); sa = sim_fpu_sign(&a); sb = sim_fpu_sign(&b); ea = booke_sim_fpu_exp(&a); eb = booke_sim_fpu_exp(&b); ei = ea + eb + 127; if (sim_fpu_is_zero (&a) || sim_fpu_is_zero (&b)) w = 0; else if (sa == sb) { if (ei >= 254) { w = EV_PMAX; EV_SET_SPEFSCR_BITS(over); } else if (ei < 1) { d = sim_fpu_zero; sim_fpu_to32 (&w, &d); w &= 0x7fffffff; /* Clear sign bit. */ } else { goto normal_mul; } } else { if (ei >= 254) { w = EV_NMAX; EV_SET_SPEFSCR_BITS(over); } else if (ei < 1) { d = sim_fpu_zero; sim_fpu_to32 (&w, &d); w |= 0x80000000; /* Set sign bit. */ } else { normal_mul: if (EV_IS_INFDENORMNAN(&a) || EV_IS_INFDENORMNAN(&b)) EV_SET_SPEFSCR_BITS(inv); sim_fpu_mul (&d, &a, &b); sim_fpu_to32 (&w, &d); } } return w;:function:e500::unsigned32:ev_fs_div:unsigned32 aa, unsigned32 bb, int inv, int over, int under, int dbz, int fg, int fx, cpu *processor sim_fpu a, b, d; unsigned32 w; int sa, sb, ea, eb, ei; sim_fpu_32to (&a, aa); sim_fpu_32to (&b, bb); sa = sim_fpu_sign(&a); sb = sim_fpu_sign(&b); ea = booke_sim_fpu_exp(&a); eb = booke_sim_fpu_exp(&b); ei = ea - eb + 127; /* Special cases to handle behaviour of e500 hardware. cf case 107543. */ if (sim_fpu_is_nan (&a) || sim_fpu_is_nan (&b) || sim_fpu_is_zero (&a) || sim_fpu_is_zero (&b)) { if (sim_fpu_is_snan (&a) || sim_fpu_is_snan (&b)) { if (bb == 0x3f800000) w = EV_PMAX; else if (aa == 0x7fc00001) w = 0x3fbffffe; else goto normal_div; } else goto normal_div; } else if (sim_fpu_is_infinity (&a) && sim_fpu_is_infinity (&b)) { if (sa == sb) sim_fpu_32to (&d, 0x3f800000); else sim_fpu_32to (&d, 0xbf800000); sim_fpu_to32 (&w, &d); } else if (sa == sb) { if (ei > 254) { w = EV_PMAX; EV_SET_SPEFSCR_BITS(over); } else if (ei <= 1) { d = sim_fpu_zero; sim_fpu_to32 (&w, &d); w &= 0x7fffffff; /* Clear sign bit. */ } else { goto normal_div; } } else { if (ei > 254) { w = EV_NMAX; EV_SET_SPEFSCR_BITS(over); } else if (ei <= 1) { d = sim_fpu_zero; sim_fpu_to32 (&w, &d); w |= 0x80000000; /* Set sign bit. */ } else { normal_div: if (EV_IS_INFDENORMNAN(&a) || EV_IS_INFDENORMNAN(&b)) EV_SET_SPEFSCR_BITS(inv); if (sim_fpu_is_zero (&b)) { if (sim_fpu_is_zero (&a)) EV_SET_SPEFSCR_BITS(dbz); else EV_SET_SPEFSCR_BITS(inv); w = sa ? EV_NMAX : EV_PMAX; } else { sim_fpu_div (&d, &a, &b); sim_fpu_to32 (&w, &d);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -