From d83276cb804d8af3985c40c92e19405f25081d05 Mon Sep 17 00:00:00 2001 From: "hp.com!davidm" <hp.com!davidm> Date: Fri, 27 Feb 2004 00:54:27 +0000 Subject: [PATCH] (compile_reg): Take extra ia64_reg_info-pointer argument. (build_script): Adjust for extra argument to compile_reg(). Fix the primary-NaT compilation such that it always updates IA64_REGPRI_UNAT_MEM. (run_script): For IA64_INSN_SETNET_MEMSTK, set the location based on IA64_REG_PRI_UNAT_MEM and don't forget to turn on the MEMSTK_NAT bit. (Logical change 1.178) --- src/ia64/Gscript-ia64.c | 56 ++++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/src/ia64/Gscript-ia64.c b/src/ia64/Gscript-ia64.c index bcf3ee74..40a97dc4 100644 --- a/src/ia64/Gscript-ia64.c +++ b/src/ia64/Gscript-ia64.c @@ -294,9 +294,9 @@ emit_nat_info (struct ia64_state_record *sr, int i, struct ia64_script *script) } static void -compile_reg (struct ia64_state_record *sr, int i, struct ia64_script *script) +compile_reg (struct ia64_state_record *sr, int i, struct ia64_reg_info *r, + struct ia64_script *script) { - struct ia64_reg_info *r = sr->curr.reg + i; enum ia64_script_insn_opcode opc; unsigned long val, rval; struct ia64_script_insn insn; @@ -439,6 +439,7 @@ static inline int build_script (struct cursor *c, struct ia64_script *script) { int num_regs, i, ret, regorder[IA64_NUM_PREGS - 3]; + struct ia64_reg_info *pri_unat; struct ia64_state_record sr; struct ia64_script_insn insn; @@ -461,26 +462,36 @@ build_script (struct cursor *c, struct ia64_script *script) script_emit (script, insn); } else - compile_reg (&sr, IA64_REG_PSP, script); + compile_reg (&sr, IA64_REG_PSP, sr.curr.reg + IA64_REG_PSP, script); - /* Second, compile the update for the primary UNaT: */ + /* Second, compile the update for the primary UNaT, if any: */ - if (sr.when_target < sr.curr.reg[IA64_REG_PRI_UNAT_GR].when) - i = IA64_REG_PRI_UNAT_MEM; - else if (sr.when_target < sr.curr.reg[IA64_REG_PRI_UNAT_MEM].when) - i = IA64_REG_PRI_UNAT_GR; - else if (sr.curr.reg[IA64_REG_PRI_UNAT_MEM].when > - sr.curr.reg[IA64_REG_PRI_UNAT_GR].when) - i = IA64_REG_PRI_UNAT_MEM; - else - i = IA64_REG_PRI_UNAT_GR; - compile_reg (&sr, i, script); + if (sr.when_target >= sr.curr.reg[IA64_REG_PRI_UNAT_GR].when + || sr.when_target >= sr.curr.reg[IA64_REG_PRI_UNAT_MEM].when) + { + if (sr.when_target < sr.curr.reg[IA64_REG_PRI_UNAT_GR].when) + /* (primary) NaT bits were saved to memory only */ + pri_unat = sr.curr.reg + IA64_REG_PRI_UNAT_MEM; + else if (sr.when_target < sr.curr.reg[IA64_REG_PRI_UNAT_MEM].when) + /* (primary) NaT bits were saved to a register only */ + pri_unat = sr.curr.reg + IA64_REG_PRI_UNAT_MEM; + else if (sr.curr.reg[IA64_REG_PRI_UNAT_MEM].when > + sr.curr.reg[IA64_REG_PRI_UNAT_GR].when) + /* (primary) NaT bits were last saved to memory */ + pri_unat = sr.curr.reg + IA64_REG_PRI_UNAT_MEM; + else + /* (primary) NaT bits were last saved to a register */ + pri_unat = sr.curr.reg + IA64_REG_PRI_UNAT_GR; + + /* Note: we always store the final primary-UNaT location in UNAT_MEM. */ + compile_reg (&sr, IA64_REG_PRI_UNAT_MEM, pri_unat, script); + } /* Third, compile the other register in decreasing order of WHEN values. */ num_regs = sort_regs (&sr, regorder); for (i = 0; i < num_regs; ++i) - compile_reg (&sr, regorder[i], script); + compile_reg (&sr, regorder[i], sr.curr.reg + regorder[i], script); script->abi_marker = sr.abi_marker; script_finalize (script, c, &sr); @@ -497,9 +508,9 @@ static inline int run_script (struct ia64_script *script, struct cursor *c) { struct ia64_script_insn *ip, *limit, next_insn; - unw_word_t val, unat_addr; unsigned long opc, dst; ia64_loc_t loc; + unw_word_t val; int ret; c->pi = script->pi; @@ -550,10 +561,15 @@ run_script (struct ia64_script *script, struct cursor *c) break; case IA64_INSN_SETNAT_MEMSTK: - if ((ret = ia64_get (c, c->loc[IA64_REG_PRI_UNAT_MEM], - &unat_addr)) < 0) - return ret; - loc = IA64_LOC_ADDR (unat_addr, IA64_LOC_TYPE_MEMSTK_NAT); + loc = c->loc[IA64_REG_PRI_UNAT_MEM]; + /* This is a fast and clean, if somewhat verbose way of + turning on bit 1 in the first word. */ + if (IA64_IS_REG_LOC (loc)) + loc = IA64_LOC_REG (IA64_GET_REG (loc), + IA64_LOC_TYPE_MEMSTK_NAT); + else + loc = IA64_LOC_ADDR (IA64_GET_ADDR (loc), + IA64_LOC_TYPE_MEMSTK_NAT); break; case IA64_INSN_INC_PSP: