summaryrefslogtreecommitdiffstats
path: root/sys/contrib/ia64/libuwx/src/uwx_context.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/ia64/libuwx/src/uwx_context.c')
-rw-r--r--sys/contrib/ia64/libuwx/src/uwx_context.c329
1 files changed, 329 insertions, 0 deletions
diff --git a/sys/contrib/ia64/libuwx/src/uwx_context.c b/sys/contrib/ia64/libuwx/src/uwx_context.c
new file mode 100644
index 0000000..9da3db3
--- /dev/null
+++ b/sys/contrib/ia64/libuwx/src/uwx_context.c
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2002,2003 Hewlett-Packard Company
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "uwx_env.h"
+#include "uwx_context.h"
+#include "uwx_scoreboard.h"
+#include "uwx_trace.h"
+
+int uwx_init_context(
+ struct uwx_env *env,
+ uint64_t ip,
+ uint64_t sp,
+ uint64_t bsp,
+ uint64_t cfm)
+{
+ int i;
+
+ if (env == 0)
+ return UWX_ERR_NOENV;
+
+ env->context.special[UWX_REG_IP] = ip;
+ env->context.special[UWX_REG_SP] = sp;
+ env->context.special[UWX_REG_BSP] = bsp;
+ env->context.special[UWX_REG_CFM] = cfm;
+ for (i = UWX_REG_RP; i < NSPECIALREG; i++)
+ env->context.special[i] = 0;
+ for (i = 0; i < NPRESERVEDGR; i++)
+ env->context.gr[i] = 0;
+ env->context.valid_regs = VALID_BASIC4;
+ env->rstate = 0;
+ (void)uwx_init_history(env);
+ return UWX_OK;
+}
+
+int uwx_get_reg(struct uwx_env *env, int regid, uint64_t *valp)
+{
+ int status;
+ int sor;
+ int rrb_gr;
+ uint64_t bsp;
+ int n;
+
+ if (env == 0)
+ return UWX_ERR_NOENV;
+
+ status = UWX_OK;
+
+ if (regid < NSPECIALREG && (env->context.valid_regs & (1 << regid)))
+ *valp = env->context.special[regid];
+ else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7) &&
+ (env->context.valid_regs &
+ (1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT))) )
+ *valp = env->context.gr[regid - UWX_REG_GR(4)];
+ else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
+ if (env->copyin == 0)
+ return UWX_ERR_NOCALLBACKS;
+ bsp = env->context.special[UWX_REG_BSP];
+ TRACE_C_GET_REG(regid, bsp)
+ regid -= UWX_REG_GR(32);
+ sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8;
+ rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f;
+ if (sor != 0 && rrb_gr != 0 && regid < sor) {
+ TRACE_C_ROTATE_GR(regid, sor, rrb_gr, (regid+rrb_gr)%sor)
+ regid = (regid + rrb_gr) % sor;
+ }
+ bsp = uwx_add_to_bsp(bsp, regid);
+ n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)valp,
+ bsp, DWORDSZ, env->cb_token);
+ if (n != DWORDSZ)
+ status = UWX_ERR_COPYIN_RSTK;
+ }
+ else if (regid == UWX_REG_GR(0))
+ *valp = 0;
+ else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_BR(5) &&
+ (env->context.valid_regs &
+ (1 << (regid - UWX_REG_BR(1) + VALID_BR_SHIFT))) )
+ *valp = env->context.br[regid - UWX_REG_BR(1)];
+ else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_BR(5) &&
+ (env->context.valid_frs & (1 << (regid - UWX_REG_FR(2)))) ) {
+ valp[0] = env->context.fr[regid - UWX_REG_FR(2)].part0;
+ valp[1] = env->context.fr[regid - UWX_REG_FR(2)].part1;
+ }
+ else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_BR(31) &&
+ (env->context.valid_frs & (1 << (regid - UWX_REG_FR(2)))) ) {
+ valp[0] = env->context.fr[regid - UWX_REG_FR(16) + 4].part0;
+ valp[1] = env->context.fr[regid - UWX_REG_FR(16) + 4].part1;
+ }
+ else if ( (regid < NSPECIALREG) ||
+ (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) ||
+ (regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) ) {
+ if (env->copyin == 0)
+ return UWX_ERR_NOCALLBACKS;
+ n = (*env->copyin)(UWX_COPYIN_REG, (char *)valp,
+ regid, DWORDSZ, env->cb_token);
+ if (n != DWORDSZ)
+ status = UWX_ERR_COPYIN_REG;
+ }
+ else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_BR(127)) {
+ if (env->copyin == 0)
+ return UWX_ERR_NOCALLBACKS;
+ n = (*env->copyin)(UWX_COPYIN_REG, (char *)valp,
+ regid, 2*DWORDSZ, env->cb_token);
+ if (n != 2*DWORDSZ)
+ status = UWX_ERR_COPYIN_REG;
+ }
+ else if (regid == UWX_REG_FR(0)) {
+ valp[0] = 0;
+ valp[1] = 0;
+ }
+ else if (regid == UWX_REG_FR(1)) {
+ valp[0] = 0x000000000000ffffULL;
+ valp[1] = 0x8000000000000000ULL;
+ }
+ else
+ status = UWX_ERR_BADREGID;
+ return status;
+}
+
+int uwx_get_nat(struct uwx_env *env, int regid, int *natp)
+{
+ int status;
+ int sor;
+ int rrb_gr;
+ uint64_t bsp;
+ uint64_t natcollp;
+ uint64_t natcoll;
+ int n;
+
+ if (env == 0)
+ return UWX_ERR_NOENV;
+
+ status = UWX_OK;
+
+ if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7) &&
+ (env->context.valid_regs &
+ (1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT))) ) {
+ *natp = (env->context.special[UWX_REG_PRIUNAT] >>
+ (regid - UWX_REG_GR(4)) ) & 0x01;
+ }
+ else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
+ if (env->copyin == 0)
+ return UWX_ERR_NOCALLBACKS;
+ bsp = env->context.special[UWX_REG_BSP];
+ regid -= UWX_REG_GR(32);
+ sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8;
+ rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f;
+ if (sor != 0 && rrb_gr != 0 && regid < sor) {
+ regid = (regid + rrb_gr) % sor;
+ }
+ bsp = uwx_add_to_bsp(bsp, regid);
+ natcollp = bsp | 0x01f8;
+ if (natcollp >= bsp)
+ n = (*env->copyin)(UWX_COPYIN_REG, (char *)&natcoll,
+ (uint64_t)UWX_REG_RNAT, DWORDSZ, env->cb_token);
+ else
+ n = (*env->copyin)(UWX_COPYIN_RSTACK, (char *)&natcoll,
+ bsp, DWORDSZ, env->cb_token);
+ if (n != DWORDSZ)
+ return UWX_ERR_COPYIN_RSTK;
+ *natp = (int)(natcoll >> (((int)bsp >> 3) & 0x3f)) & 0x01;
+ }
+ else if (regid == UWX_REG_GR(0))
+ *natp = 0;
+ else
+ status = UWX_ERR_BADREGID;
+ return status;
+}
+
+int uwx_get_spill_loc(struct uwx_env *env, int regid, uint64_t *dispp)
+{
+ int status;
+ int sor;
+ int rrb_gr;
+ uint64_t bsp;
+
+ if (env == 0)
+ return UWX_ERR_NOENV;
+
+ status = UWX_OK;
+
+ if (regid < NSPECIALREG)
+ *dispp = env->history.special[regid];
+ else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7))
+ *dispp = env->history.gr[regid - UWX_REG_GR(4)];
+ else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
+ bsp = env->context.special[UWX_REG_BSP];
+ regid -= UWX_REG_GR(32);
+ sor = (((int) env->context.special[UWX_REG_CFM] >> 14) & 0x0f) * 8;
+ rrb_gr = ((int) env->context.special[UWX_REG_CFM] >> 18) & 0x7f;
+ if (sor != 0 && rrb_gr != 0 && regid < sor)
+ regid = (regid + rrb_gr) % sor;
+ bsp = uwx_add_to_bsp(bsp, regid);
+ *dispp = UWX_DISP_RSTK(bsp);
+ }
+ else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_GR(5))
+ *dispp = env->history.br[regid - UWX_REG_BR(1)];
+ else if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5))
+ *dispp = env->history.fr[regid - UWX_REG_FR(2)];
+ else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31))
+ *dispp = env->history.fr[regid - UWX_REG_FR(16) + 4];
+ else if ( (regid >= UWX_REG_GR(1) && regid <= UWX_REG_GR(31)) ||
+ (regid >= UWX_REG_BR(0) && regid <= UWX_REG_BR(7)) ||
+ (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(127)) )
+ *dispp = UWX_DISP_REG(regid);
+ else
+ status = UWX_ERR_BADREGID;
+ return status;
+}
+
+int uwx_set_reg(struct uwx_env *env, int regid, uint64_t val)
+{
+ int status;
+
+ if (env == 0)
+ return UWX_ERR_NOENV;
+
+ if (regid < NSPECIALREG) {
+ env->context.special[regid] = val;
+ env->context.valid_regs |= 1 << regid;
+ status = UWX_OK;
+ }
+ else if (regid >= UWX_REG_GR(4) && regid <= UWX_REG_GR(7)) {
+ env->context.gr[regid - UWX_REG_GR(4)] = val;
+ env->context.valid_regs |=
+ 1 << (regid - UWX_REG_GR(4) + VALID_GR_SHIFT);
+ status = UWX_OK;
+ }
+ else if (regid >= UWX_REG_GR(32) && regid <= UWX_REG_GR(127)) {
+ status = UWX_ERR_BADREGID;
+ }
+ else if (regid >= UWX_REG_BR(1) && regid <= UWX_REG_BR(5)) {
+ env->context.br[regid - UWX_REG_BR(1)] = val;
+ env->context.valid_regs |=
+ 1 << (regid - UWX_REG_BR(1) + VALID_BR_SHIFT);
+ status = UWX_OK;
+ }
+ else
+ status = UWX_ERR_BADREGID;
+ return status;
+}
+
+int uwx_set_fr(struct uwx_env *env, int regid, uint64_t *val)
+{
+
+ if (regid >= UWX_REG_FR(2) && regid <= UWX_REG_FR(5))
+ regid -= UWX_REG_FR(2);
+ else if (regid >= UWX_REG_FR(16) && regid <= UWX_REG_FR(31))
+ regid -= UWX_REG_FR(16) - 4;
+ else
+ return UWX_ERR_BADREGID;
+
+ env->context.fr[regid].part0 = val[0];
+ env->context.fr[regid].part1 = val[1];
+ env->context.valid_frs |= 1 << regid;
+ env->nsbreg = NSBREG;
+ return UWX_OK;
+}
+
+uint64_t uwx_add_to_bsp(uint64_t bsp, int nslots)
+{
+ int bias;
+
+ /*
+ * Here's a picture of the backing store as modeled in
+ * the computations below. "X" marks NaT collections at
+ * every 0x1f8 mod 0x200 address.
+ *
+ * To make the NaT adjustments easier, we bias the current bsp
+ * by enough slots to place it at the previous NaT collection.
+ * Then we need to add the bias to the number of slots,
+ * then add 1 for every 63 slots to account for NaT collections.
+ * Then we can remove the bias again and add the adjusted
+ * number of slots to the bsp.
+ *
+ * 0 1f8 3f8
+ * +---------------------------------------------------------------+
+ * | X X|
+ * +---------------------------------------------------------------+
+ * <-------- bias -------->
+ * <--- nslots --->
+ * ^
+ * |
+ * bsp
+ * <------- adjusted (nslots + bias) ------->
+
+ * When subtracting from bsp, we bias the bsp in the opposite
+ * direction so that it is at the next NaT collection.
+ *
+ * 0 1f8 3f8
+ * +---------------------------------------------------------------+
+ * | X X|
+ * +---------------------------------------------------------------+
+ * <------- bias ------->
+ * <--- nslots --->
+ * ^
+ * |
+ * bsp
+ * <------ adjusted (nslots + bias) ------>
+ */
+
+ if (nslots > 0) {
+ bias = ((unsigned int)bsp & 0x1f8) / DWORDSZ;
+ nslots += (nslots + bias) / 63;
+ }
+ else if (nslots < 0) {
+ bias = (0x1f8 - ((unsigned int)bsp & 0x1f8)) / DWORDSZ;
+ nslots -= (-nslots + bias) / 63;
+ }
+ return bsp + nslots * DWORDSZ;
+}
OpenPOWER on IntegriCloud