From 3fc46200b15eca893e083fa3714e3680e91ac5cd Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Sun, 9 Apr 2006 00:26:08 +0000 Subject: [PATCH] * Makefile.in (s390-tdep.o): Add dependency on $(prologue_value_h). * s390-tdep.c: Include "prologue-value.h". (struct prologue_value): Remove. (pv_set_to_unknown, pv_set_to_constant, pv_set_to_register, pv_constant_last, pv_add, pv_add_constant, pv_subtract, pv_logical_and, pv_is_identical, pv_is_register): Remove. (compute_x_addr): Remove, replace by ... (s390_addr): ... this new function. (struct s390_prologue_data): Use pv_t instead of prologue_value. (s390_store, s390_load): Likewise. (s390_prologue_frame_unwind_cache): Likewise. (s390_analyze_prologue): Likewise. Also, simplify and combine several conditional statements. --- gdb/ChangeLog | 16 + gdb/Makefile.in | 3 +- gdb/s390-tdep.c | 896 ++++++++++++-------------------------------------------- 3 files changed, 203 insertions(+), 712 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 35bebaa..d9ec4c5 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,19 @@ +2006-04-09 Ulrich Weigand + + * Makefile.in (s390-tdep.o): Add dependency on $(prologue_value_h). + * s390-tdep.c: Include "prologue-value.h". + (struct prologue_value): Remove. + (pv_set_to_unknown, pv_set_to_constant, pv_set_to_register, + pv_constant_last, pv_add, pv_add_constant, pv_subtract, + pv_logical_and, pv_is_identical, pv_is_register): Remove. + (compute_x_addr): Remove, replace by ... + (s390_addr): ... this new function. + (struct s390_prologue_data): Use pv_t instead of prologue_value. + (s390_store, s390_load): Likewise. + (s390_prologue_frame_unwind_cache): Likewise. + (s390_analyze_prologue): Likewise. Also, simplify and combine + several conditional statements. + 2006-04-08 Jim Blandy * Makefile.in (COMMON_OBS): List prologue-value.o. (Omitted from diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 2dda543..3c568dd 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -2516,7 +2516,8 @@ s390-tdep.o: s390-tdep.c $(defs_h) $(arch_utils_h) $(frame_h) $(inferior_h) \ $(symtab_h) $(target_h) $(gdbcore_h) $(gdbcmd_h) $(objfiles_h) \ $(floatformat_h) $(regcache_h) $(trad_frame_h) $(frame_base_h) \ $(frame_unwind_h) $(dwarf2_frame_h) $(reggroups_h) $(regset_h) \ - $(value_h) $(gdb_assert_h) $(dis_asm_h) $(solib_svr4_h) $(s390_tdep_h) + $(value_h) $(gdb_assert_h) $(dis_asm_h) $(solib_svr4_h) \ + $(prologue_value_h) $(s390_tdep_h) scm-exp.o: scm-exp.c $(defs_h) $(symtab_h) $(gdbtypes_h) $(expression_h) \ $(parser_defs_h) $(language_h) $(value_h) $(c_lang_h) $(scm_lang_h) \ $(scm_tags_h) diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c index b7c7001..1e58612 100644 --- a/gdb/s390-tdep.c +++ b/gdb/s390-tdep.c @@ -44,6 +44,7 @@ #include "gdb_assert.h" #include "dis-asm.h" #include "solib-svr4.h" +#include "prologue-value.h" #include "s390-tdep.h" @@ -476,330 +477,6 @@ s390_regset_from_core_section (struct gdbarch *gdbarch, } -/* Prologue analysis. */ - -/* When we analyze a prologue, we're really doing 'abstract - interpretation' or 'pseudo-evaluation': running the function's code - in simulation, but using conservative approximations of the values - it would have when it actually runs. For example, if our function - starts with the instruction: - - ahi r1, 42 # add halfword immediate 42 to r1 - - we don't know exactly what value will be in r1 after executing this - instruction, but we do know it'll be 42 greater than its original - value. - - If we then see an instruction like: - - ahi r1, 22 # add halfword immediate 22 to r1 - - we still don't know what r1's value is, but again, we can say it is - now 64 greater than its original value. - - If the next instruction were: - - lr r2, r1 # set r2 to r1's value - - then we can say that r2's value is now the original value of r1 - plus 64. And so on. - - Of course, this can only go so far before it gets unreasonable. If - we wanted to be able to say anything about the value of r1 after - the instruction: - - xr r1, r3 # exclusive-or r1 and r3, place result in r1 - - then things would get pretty complex. But remember, we're just - doing a conservative approximation; if exclusive-or instructions - aren't relevant to prologues, we can just say r1's value is now - 'unknown'. We can ignore things that are too complex, if that loss - of information is acceptable for our application. - - Once you've reached an instruction that you don't know how to - simulate, you stop. Now you examine the state of the registers and - stack slots you've kept track of. For example: - - - To see how large your stack frame is, just check the value of sp; - if it's the original value of sp minus a constant, then that - constant is the stack frame's size. If the sp's value has been - marked as 'unknown', then that means the prologue has done - something too complex for us to track, and we don't know the - frame size. - - - To see whether we've saved the SP in the current frame's back - chain slot, we just check whether the current value of the back - chain stack slot is the original value of the sp. - - Sure, this takes some work. But prologue analyzers aren't - quick-and-simple pattern patching to recognize a few fixed prologue - forms any more; they're big, hairy functions. Along with inferior - function calls, prologue analysis accounts for a substantial - portion of the time needed to stabilize a GDB port. So I think - it's worthwhile to look for an approach that will be easier to - understand and maintain. In the approach used here: - - - It's easier to see that the analyzer is correct: you just see - whether the analyzer properly (albiet conservatively) simulates - the effect of each instruction. - - - It's easier to extend the analyzer: you can add support for new - instructions, and know that you haven't broken anything that - wasn't already broken before. - - - It's orthogonal: to gather new information, you don't need to - complicate the code for each instruction. As long as your domain - of conservative values is already detailed enough to tell you - what you need, then all the existing instruction simulations are - already gathering the right data for you. - - A 'struct prologue_value' is a conservative approximation of the - real value the register or stack slot will have. */ - -struct prologue_value { - - /* What sort of value is this? This determines the interpretation - of subsequent fields. */ - enum { - - /* We don't know anything about the value. This is also used for - values we could have kept track of, when doing so would have - been too complex and we don't want to bother. The bottom of - our lattice. */ - pv_unknown, - - /* A known constant. K is its value. */ - pv_constant, - - /* The value that register REG originally had *UPON ENTRY TO THE - FUNCTION*, plus K. If K is zero, this means, obviously, just - the value REG had upon entry to the function. REG is a GDB - register number. Before we start interpreting, we initialize - every register R to { pv_register, R, 0 }. */ - pv_register, - - } kind; - - /* The meanings of the following fields depend on 'kind'; see the - comments for the specific 'kind' values. */ - int reg; - CORE_ADDR k; -}; - - -/* Set V to be unknown. */ -static void -pv_set_to_unknown (struct prologue_value *v) -{ - v->kind = pv_unknown; -} - - -/* Set V to the constant K. */ -static void -pv_set_to_constant (struct prologue_value *v, CORE_ADDR k) -{ - v->kind = pv_constant; - v->k = k; -} - - -/* Set V to the original value of register REG, plus K. */ -static void -pv_set_to_register (struct prologue_value *v, int reg, CORE_ADDR k) -{ - v->kind = pv_register; - v->reg = reg; - v->k = k; -} - - -/* If one of *A and *B is a constant, and the other isn't, swap the - pointers as necessary to ensure that *B points to the constant. - This can reduce the number of cases we need to analyze in the - functions below. */ -static void -pv_constant_last (struct prologue_value **a, - struct prologue_value **b) -{ - if ((*a)->kind == pv_constant - && (*b)->kind != pv_constant) - { - struct prologue_value *temp = *a; - *a = *b; - *b = temp; - } -} - - -/* Set SUM to the sum of A and B. SUM, A, and B may point to the same - 'struct prologue_value' object. */ -static void -pv_add (struct prologue_value *sum, - struct prologue_value *a, - struct prologue_value *b) -{ - pv_constant_last (&a, &b); - - /* We can handle adding constants to registers, and other constants. */ - if (b->kind == pv_constant - && (a->kind == pv_register - || a->kind == pv_constant)) - { - sum->kind = a->kind; - sum->reg = a->reg; /* not meaningful if a is pv_constant, but - harmless */ - sum->k = a->k + b->k; - } - - /* Anything else we don't know how to add. We don't have a - representation for, say, the sum of two registers, or a multiple - of a register's value (adding a register to itself). */ - else - sum->kind = pv_unknown; -} - - -/* Add the constant K to V. */ -static void -pv_add_constant (struct prologue_value *v, CORE_ADDR k) -{ - struct prologue_value pv_k; - - /* Rather than thinking of all the cases we can and can't handle, - we'll just let pv_add take care of that for us. */ - pv_set_to_constant (&pv_k, k); - pv_add (v, v, &pv_k); -} - - -/* Subtract B from A, and put the result in DIFF. - - This isn't quite the same as negating B and adding it to A, since - we don't have a representation for the negation of anything but a - constant. For example, we can't negate { pv_register, R1, 10 }, - but we do know that { pv_register, R1, 10 } minus { pv_register, - R1, 5 } is { pv_constant, , 5 }. - - This means, for example, that we can subtract two stack addresses; - they're both relative to the original SP. Since the frame pointer - is set based on the SP, its value will be the original SP plus some - constant (probably zero), so we can use its value just fine. */ -static void -pv_subtract (struct prologue_value *diff, - struct prologue_value *a, - struct prologue_value *b) -{ - pv_constant_last (&a, &b); - - /* We can subtract a constant from another constant, or from a - register. */ - if (b->kind == pv_constant - && (a->kind == pv_register - || a->kind == pv_constant)) - { - diff->kind = a->kind; - diff->reg = a->reg; /* not always meaningful, but harmless */ - diff->k = a->k - b->k; - } - - /* We can subtract a register from itself, yielding a constant. */ - else if (a->kind == pv_register - && b->kind == pv_register - && a->reg == b->reg) - { - diff->kind = pv_constant; - diff->k = a->k - b->k; - } - - /* We don't know how to subtract anything else. */ - else - diff->kind = pv_unknown; -} - - -/* Set AND to the logical and of A and B. */ -static void -pv_logical_and (struct prologue_value *and, - struct prologue_value *a, - struct prologue_value *b) -{ - pv_constant_last (&a, &b); - - /* We can 'and' two constants. */ - if (a->kind == pv_constant - && b->kind == pv_constant) - { - and->kind = pv_constant; - and->k = a->k & b->k; - } - - /* We can 'and' anything with the constant zero. */ - else if (b->kind == pv_constant - && b->k == 0) - { - and->kind = pv_constant; - and->k = 0; - } - - /* We can 'and' anything with ~0. */ - else if (b->kind == pv_constant - && b->k == ~ (CORE_ADDR) 0) - *and = *a; - - /* We can 'and' a register with itself. */ - else if (a->kind == pv_register - && b->kind == pv_register - && a->reg == b->reg - && a->k == b->k) - *and = *a; - - /* Otherwise, we don't know. */ - else - pv_set_to_unknown (and); -} - - -/* Return non-zero iff A and B are identical expressions. - - This is not the same as asking if the two values are equal; the - result of such a comparison would have to be a pv_boolean, and - asking whether two 'unknown' values were equal would give you - pv_maybe. Same for comparing, say, { pv_register, R1, 0 } and { - pv_register, R2, 0}. Instead, this is asking whether the two - representations are the same. */ -static int -pv_is_identical (struct prologue_value *a, - struct prologue_value *b) -{ - if (a->kind != b->kind) - return 0; - - switch (a->kind) - { - case pv_unknown: - return 1; - case pv_constant: - return (a->k == b->k); - case pv_register: - return (a->reg == b->reg && a->k == b->k); - default: - gdb_assert (0); - } -} - - -/* Return non-zero if A is the original value of register number R - plus K, zero otherwise. */ -static int -pv_is_register (struct prologue_value *a, int r, CORE_ADDR k) -{ - return (a->kind == pv_register - && a->reg == r - && a->k == k); -} - - /* Decoding S/390 instructions. */ /* Named opcode values for the S/390 instructions we recognize. Some @@ -1032,35 +709,7 @@ is_rxy (bfd_byte *insn, int op1, int op2, } -/* Set ADDR to the effective address for an X-style instruction, like: - - L R1, D2(X2, B2) - - Here, X2 and B2 are registers, and D2 is a signed 20-bit - constant; the effective address is the sum of all three. If either - X2 or B2 are zero, then it doesn't contribute to the sum --- this - means that r0 can't be used as either X2 or B2. - - GPR is an array of general register values, indexed by GPR number, - not GDB register number. */ -static void -compute_x_addr (struct prologue_value *addr, - struct prologue_value *gpr, - int d2, unsigned int x2, unsigned int b2) -{ - /* We can't just add stuff directly in addr; it might alias some of - the registers we need to read. */ - struct prologue_value result; - - pv_set_to_constant (&result, d2); - if (x2) - pv_add (&result, &result, &gpr[x2]); - if (b2) - pv_add (&result, &result, &gpr[b2]); - - *addr = result; -} - +/* Prologue analysis. */ #define S390_NUM_GPRS 16 #define S390_NUM_FPRS 16 @@ -1072,10 +721,10 @@ struct s390_prologue_data { int fpr_size; /* The general-purpose registers. */ - struct prologue_value gpr[S390_NUM_GPRS]; + pv_t gpr[S390_NUM_GPRS]; /* The floating-point registers. */ - struct prologue_value fpr[S390_NUM_FPRS]; + pv_t fpr[S390_NUM_FPRS]; /* The offset relative to the CFA where the incoming GPR N was saved by the function prologue. 0 if not saved or unknown. */ @@ -1089,22 +738,45 @@ struct s390_prologue_data { int back_chain_saved_p; }; -/* Do a SIZE-byte store of VALUE to ADDR. */ +/* Return the effective address for an X-style instruction, like: + + L R1, D2(X2, B2) + + Here, X2 and B2 are registers, and D2 is a signed 20-bit + constant; the effective address is the sum of all three. If either + X2 or B2 are zero, then it doesn't contribute to the sum --- this + means that r0 can't be used as either X2 or B2. */ +static pv_t +s390_addr (struct s390_prologue_data *data, + int d2, unsigned int x2, unsigned int b2) +{ + pv_t result; + + result = pv_constant (d2); + if (x2) + result = pv_add (result, data->gpr[x2]); + if (b2) + result = pv_add (result, data->gpr[b2]); + + return result; +} + +/* Do a SIZE-byte store of VALUE to D2(X2,B2). */ static void -s390_store (struct prologue_value *addr, - CORE_ADDR size, - struct prologue_value *value, - struct s390_prologue_data *data) +s390_store (struct s390_prologue_data *data, + int d2, unsigned int x2, unsigned int b2, CORE_ADDR size, + pv_t value) { - struct prologue_value cfa, offset; + pv_t addr = s390_addr (data, d2, x2, b2); + pv_t cfa, offset; int i; /* Check whether we are storing the backchain. */ - pv_subtract (&offset, &data->gpr[S390_SP_REGNUM - S390_R0_REGNUM], addr); + offset = pv_subtract (data->gpr[S390_SP_REGNUM - S390_R0_REGNUM], addr); - if (offset.kind == pv_constant && offset.k == 0) + if (pv_is_constant (offset) && offset.k == 0) if (size == data->gpr_size - && pv_is_register (value, S390_SP_REGNUM, 0)) + && pv_is_register_k (value, S390_SP_REGNUM, 0)) { data->back_chain_saved_p = 1; return; @@ -1112,10 +784,10 @@ s390_store (struct prologue_value *addr, /* Check whether we are storing a register into the stack. */ - pv_set_to_register (&cfa, S390_SP_REGNUM, 16 * data->gpr_size + 32); - pv_subtract (&offset, &cfa, addr); + cfa = pv_register (S390_SP_REGNUM, 16 * data->gpr_size + 32); + offset = pv_subtract (cfa, addr); - if (offset.kind == pv_constant + if (pv_is_constant (offset) && offset.k < INT_MAX && offset.k > 0 && offset.k % data->gpr_size == 0) { @@ -1125,7 +797,7 @@ s390_store (struct prologue_value *addr, for (i = 0; i < S390_NUM_GPRS; i++) if (size == data->gpr_size - && pv_is_register (value, S390_R0_REGNUM + i, 0)) + && pv_is_register_k (value, S390_R0_REGNUM + i, 0)) if (data->gpr_slot[i] == 0 || data->gpr_slot[i] > offset.k) { @@ -1135,7 +807,7 @@ s390_store (struct prologue_value *addr, for (i = 0; i < S390_NUM_FPRS; i++) if (size == data->fpr_size - && pv_is_register (value, S390_F0_REGNUM + i, 0)) + && pv_is_register_k (value, S390_F0_REGNUM + i, 0)) if (data->fpr_slot[i] == 0 || data->fpr_slot[i] > offset.k) { @@ -1153,14 +825,14 @@ s390_store (struct prologue_value *addr, stores. Thus every store we cannot recognize does not hit our data. */ } -/* Do a SIZE-byte load from ADDR into VALUE. */ -static void -s390_load (struct prologue_value *addr, - CORE_ADDR size, - struct prologue_value *value, - struct s390_prologue_data *data) +/* Do a SIZE-byte load from D2(X2,B2). */ +static pv_t +s390_load (struct s390_prologue_data *data, + int d2, unsigned int x2, unsigned int b2, CORE_ADDR size) + { - struct prologue_value cfa, offset; + pv_t addr = s390_addr (data, d2, x2, b2); + pv_t cfa, offset; int i; /* If it's a load from an in-line constant pool, then we can @@ -1168,43 +840,34 @@ s390_load (struct prologue_value *addr, going to change between the time the processor actually executed it creating the current frame, and the time when we're analyzing the code to unwind past that frame. */ - if (addr->kind == pv_constant) + if (pv_is_constant (addr)) { struct section_table *secp; - secp = target_section_by_addr (¤t_target, addr->k); + secp = target_section_by_addr (¤t_target, addr.k); if (secp != NULL && (bfd_get_section_flags (secp->bfd, secp->the_bfd_section) & SEC_READONLY)) - { - pv_set_to_constant (value, read_memory_integer (addr->k, size)); - return; - } + return pv_constant (read_memory_integer (addr.k, size)); } /* Check whether we are accessing one of our save slots. */ - pv_set_to_register (&cfa, S390_SP_REGNUM, 16 * data->gpr_size + 32); - pv_subtract (&offset, &cfa, addr); + cfa = pv_register (S390_SP_REGNUM, 16 * data->gpr_size + 32); + offset = pv_subtract (cfa, addr); - if (offset.kind == pv_constant + if (pv_is_constant (offset) && offset.k < INT_MAX && offset.k > 0) { for (i = 0; i < S390_NUM_GPRS; i++) if (offset.k == data->gpr_slot[i]) - { - pv_set_to_register (value, S390_R0_REGNUM + i, 0); - return; - } + return pv_register (S390_R0_REGNUM + i, 0); for (i = 0; i < S390_NUM_FPRS; i++) if (offset.k == data->fpr_slot[i]) - { - pv_set_to_register (value, S390_F0_REGNUM + i, 0); - return; - } + return pv_register (S390_F0_REGNUM + i, 0); } /* Otherwise, we don't know the value. */ - pv_set_to_unknown (value); + return pv_unknown (); } @@ -1245,10 +908,10 @@ s390_analyze_prologue (struct gdbarch *gdbarch, data->fpr_size = 8; for (i = 0; i < S390_NUM_GPRS; i++) - pv_set_to_register (&data->gpr[i], S390_R0_REGNUM + i, 0); + data->gpr[i] = pv_register (S390_R0_REGNUM + i, 0); for (i = 0; i < S390_NUM_FPRS; i++) - pv_set_to_register (&data->fpr[i], S390_F0_REGNUM + i, 0); + data->fpr[i] = pv_register (S390_F0_REGNUM + i, 0); for (i = 0; i < S390_NUM_GPRS; i++) data->gpr_slot[i] = 0; @@ -1266,13 +929,17 @@ s390_analyze_prologue (struct gdbarch *gdbarch, bfd_byte insn[S390_MAX_INSTR_SIZE]; int insn_len = s390_readinstruction (insn, pc); + bfd_byte dummy[S390_MAX_INSTR_SIZE] = { 0 }; + bfd_byte *insn32 = word_size == 4 ? insn : dummy; + bfd_byte *insn64 = word_size == 8 ? insn : dummy; + /* Fields for various kinds of instructions. */ unsigned int b2, r1, r2, x2, r3; int i2, d2; /* The values of SP and FP before this instruction, for detecting instructions that change them. */ - struct prologue_value pre_insn_sp, pre_insn_fp; + pv_t pre_insn_sp, pre_insn_fp; /* Likewise for the flag whether the back chain was saved. */ int pre_insn_back_chain_saved_p; @@ -1289,320 +956,126 @@ s390_analyze_prologue (struct gdbarch *gdbarch, pre_insn_fp = data->gpr[S390_FRAME_REGNUM - S390_R0_REGNUM]; pre_insn_back_chain_saved_p = data->back_chain_saved_p; - /* LHI r1, i2 --- load halfword immediate */ - if (word_size == 4 - && is_ri (insn, op1_lhi, op2_lhi, &r1, &i2)) - pv_set_to_constant (&data->gpr[r1], i2); - - /* LGHI r1, i2 --- load halfword immediate (64-bit version) */ - else if (word_size == 8 - && is_ri (insn, op1_lghi, op2_lghi, &r1, &i2)) - pv_set_to_constant (&data->gpr[r1], i2); - - /* LGFI r1, i2 --- load fullword immediate */ - else if (is_ril (insn, op1_lgfi, op2_lgfi, &r1, &i2)) - pv_set_to_constant (&data->gpr[r1], i2); - - /* LR r1, r2 --- load from register */ - else if (word_size == 4 - && is_rr (insn, op_lr, &r1, &r2)) - data->gpr[r1] = data->gpr[r2]; - - /* LGR r1, r2 --- load from register (64-bit version) */ - else if (word_size == 8 - && is_rre (insn, op_lgr, &r1, &r2)) - data->gpr[r1] = data->gpr[r2]; - - /* L r1, d2(x2, b2) --- load */ - else if (word_size == 4 - && is_rx (insn, op_l, &r1, &d2, &x2, &b2)) - { - struct prologue_value addr; - - compute_x_addr (&addr, data->gpr, d2, x2, b2); - s390_load (&addr, 4, &data->gpr[r1], data); - } - - /* LY r1, d2(x2, b2) --- load (long-displacement version) */ - else if (word_size == 4 - && is_rxy (insn, op1_ly, op2_ly, &r1, &d2, &x2, &b2)) - { - struct prologue_value addr; - - compute_x_addr (&addr, data->gpr, d2, x2, b2); - s390_load (&addr, 4, &data->gpr[r1], data); - } - - /* LG r1, d2(x2, b2) --- load (64-bit version) */ - else if (word_size == 8 - && is_rxy (insn, op1_lg, op2_lg, &r1, &d2, &x2, &b2)) - { - struct prologue_value addr; - - compute_x_addr (&addr, data->gpr, d2, x2, b2); - s390_load (&addr, 8, &data->gpr[r1], data); - } - - /* ST r1, d2(x2, b2) --- store */ - else if (word_size == 4 - && is_rx (insn, op_st, &r1, &d2, &x2, &b2)) - { - struct prologue_value addr; - - compute_x_addr (&addr, data->gpr, d2, x2, b2); - s390_store (&addr, 4, &data->gpr[r1], data); - } - /* STY r1, d2(x2, b2) --- store (long-displacement version) */ - else if (word_size == 4 - && is_rxy (insn, op1_sty, op2_sty, &r1, &d2, &x2, &b2)) - { - struct prologue_value addr; - - compute_x_addr (&addr, data->gpr, d2, x2, b2); - s390_store (&addr, 4, &data->gpr[r1], data); - } - - /* STG r1, d2(x2, b2) --- store (64-bit version) */ - else if (word_size == 8 - && is_rxy (insn, op1_stg, op2_stg, &r1, &d2, &x2, &b2)) - { - struct prologue_value addr; - - compute_x_addr (&addr, data->gpr, d2, x2, b2); - s390_store (&addr, 8, &data->gpr[r1], data); - } - - /* STD r1, d2(x2,b2) --- store floating-point register */ + /* LHI r1, i2 --- load halfword immediate. */ + /* LGHI r1, i2 --- load halfword immediate (64-bit version). */ + /* LGFI r1, i2 --- load fullword immediate. */ + if (is_ri (insn32, op1_lhi, op2_lhi, &r1, &i2) + || is_ri (insn64, op1_lghi, op2_lghi, &r1, &i2) + || is_ril (insn, op1_lgfi, op2_lgfi, &r1, &i2)) + data->gpr[r1] = pv_constant (i2); + + /* LR r1, r2 --- load from register. */ + /* LGR r1, r2 --- load from register (64-bit version). */ + else if (is_rr (insn32, op_lr, &r1, &r2) + || is_rre (insn64, op_lgr, &r1, &r2)) + data->gpr[r1] = data->gpr[r2]; + + /* L r1, d2(x2, b2) --- load. */ + /* LY r1, d2(x2, b2) --- load (long-displacement version). */ + /* LG r1, d2(x2, b2) --- load (64-bit version). */ + else if (is_rx (insn32, op_l, &r1, &d2, &x2, &b2) + || is_rxy (insn32, op1_ly, op2_ly, &r1, &d2, &x2, &b2) + || is_rxy (insn64, op1_lg, op2_lg, &r1, &d2, &x2, &b2)) + data->gpr[r1] = s390_load (data, d2, x2, b2, data->gpr_size); + + /* ST r1, d2(x2, b2) --- store. */ + /* STY r1, d2(x2, b2) --- store (long-displacement version). */ + /* STG r1, d2(x2, b2) --- store (64-bit version). */ + else if (is_rx (insn32, op_st, &r1, &d2, &x2, &b2) + || is_rxy (insn32, op1_sty, op2_sty, &r1, &d2, &x2, &b2) + || is_rxy (insn64, op1_stg, op2_stg, &r1, &d2, &x2, &b2)) + s390_store (data, d2, x2, b2, data->gpr_size, data->gpr[r1]); + + /* STD r1, d2(x2,b2) --- store floating-point register. */ else if (is_rx (insn, op_std, &r1, &d2, &x2, &b2)) + s390_store (data, d2, x2, b2, data->fpr_size, data->fpr[r1]); + + /* STM r1, r3, d2(b2) --- store multiple. */ + /* STMY r1, r3, d2(b2) --- store multiple (long-displacement version). */ + /* STMG r1, r3, d2(b2) --- store multiple (64-bit version). */ + else if (is_rs (insn32, op_stm, &r1, &r3, &d2, &b2) + || is_rsy (insn32, op1_stmy, op2_stmy, &r1, &r3, &d2, &b2) + || is_rsy (insn64, op1_stmg, op2_stmg, &r1, &r3, &d2, &b2)) { - struct prologue_value addr; - - compute_x_addr (&addr, data->gpr, d2, x2, b2); - s390_store (&addr, 8, &data->fpr[r1], data); + for (; r1 <= r3; r1++, d2 += data->gpr_size) + s390_store (data, d2, 0, b2, data->gpr_size, data->gpr[r1]); } - /* STM r1, r3, d2(b2) --- store multiple */ - else if (word_size == 4 - && is_rs (insn, op_stm, &r1, &r3, &d2, &b2)) - { - int regnum; - int offset; - struct prologue_value addr; - - for (regnum = r1, offset = 0; - regnum <= r3; - regnum++, offset += 4) - { - compute_x_addr (&addr, data->gpr, d2 + offset, 0, b2); - s390_store (&addr, 4, &data->gpr[regnum], data); - } - } - - /* STMY r1, r3, d2(b2) --- store multiple (long-displacement version) */ - else if (word_size == 4 - && is_rsy (insn, op1_stmy, op2_stmy, &r1, &r3, &d2, &b2)) - { - int regnum; - int offset; - struct prologue_value addr; - - for (regnum = r1, offset = 0; - regnum <= r3; - regnum++, offset += 4) - { - compute_x_addr (&addr, data->gpr, d2 + offset, 0, b2); - s390_store (&addr, 4, &data->gpr[regnum], data); - } - } - - /* STMG r1, r3, d2(b2) --- store multiple (64-bit version) */ - else if (word_size == 8 - && is_rsy (insn, op1_stmg, op2_stmg, &r1, &r3, &d2, &b2)) - { - int regnum; - int offset; - struct prologue_value addr; - - for (regnum = r1, offset = 0; - regnum <= r3; - regnum++, offset += 8) - { - compute_x_addr (&addr, data->gpr, d2 + offset, 0, b2); - s390_store (&addr, 8, &data->gpr[regnum], data); - } - } - - /* AHI r1, i2 --- add halfword immediate */ - else if (word_size == 4 - && is_ri (insn, op1_ahi, op2_ahi, &r1, &i2)) - pv_add_constant (&data->gpr[r1], i2); - - /* AGHI r1, i2 --- add halfword immediate (64-bit version) */ - else if (word_size == 8 - && is_ri (insn, op1_aghi, op2_aghi, &r1, &i2)) - pv_add_constant (&data->gpr[r1], i2); - - /* AFI r1, i2 --- add fullword immediate */ - else if (word_size == 4 - && is_ril (insn, op1_afi, op2_afi, &r1, &i2)) - pv_add_constant (&data->gpr[r1], i2); - - /* AGFI r1, i2 --- add fullword immediate (64-bit version) */ - else if (word_size == 8 - && is_ril (insn, op1_agfi, op2_agfi, &r1, &i2)) - pv_add_constant (&data->gpr[r1], i2); - - /* ALFI r1, i2 --- add logical immediate */ - else if (word_size == 4 - && is_ril (insn, op1_alfi, op2_alfi, &r1, &i2)) - pv_add_constant (&data->gpr[r1], (CORE_ADDR)i2 & 0xffffffff); - - /* ALGFI r1, i2 --- add logical immediate (64-bit version) */ - else if (word_size == 8 - && is_ril (insn, op1_algfi, op2_algfi, &r1, &i2)) - pv_add_constant (&data->gpr[r1], (CORE_ADDR)i2 & 0xffffffff); - - /* AR r1, r2 -- add register */ - else if (word_size == 4 - && is_rr (insn, op_ar, &r1, &r2)) - pv_add (&data->gpr[r1], &data->gpr[r1], &data->gpr[r2]); - - /* AGR r1, r2 -- add register (64-bit version) */ - else if (word_size == 8 - && is_rre (insn, op_agr, &r1, &r2)) - pv_add (&data->gpr[r1], &data->gpr[r1], &data->gpr[r2]); - - /* A r1, d2(x2, b2) -- add */ - else if (word_size == 4 - && is_rx (insn, op_a, &r1, &d2, &x2, &b2)) - { - struct prologue_value addr; - struct prologue_value value; - - compute_x_addr (&addr, data->gpr, d2, x2, b2); - s390_load (&addr, 4, &value, data); - - pv_add (&data->gpr[r1], &data->gpr[r1], &value); - } - - /* AY r1, d2(x2, b2) -- add (long-displacement version) */ - else if (word_size == 4 - && is_rxy (insn, op1_ay, op2_ay, &r1, &d2, &x2, &b2)) - { - struct prologue_value addr; - struct prologue_value value; - - compute_x_addr (&addr, data->gpr, d2, x2, b2); - s390_load (&addr, 4, &value, data); - - pv_add (&data->gpr[r1], &data->gpr[r1], &value); - } - - /* AG r1, d2(x2, b2) -- add (64-bit version) */ - else if (word_size == 8 - && is_rxy (insn, op1_ag, op2_ag, &r1, &d2, &x2, &b2)) - { - struct prologue_value addr; - struct prologue_value value; - - compute_x_addr (&addr, data->gpr, d2, x2, b2); - s390_load (&addr, 8, &value, data); - - pv_add (&data->gpr[r1], &data->gpr[r1], &value); - } - - /* SLFI r1, i2 --- subtract logical immediate */ - else if (word_size == 4 - && is_ril (insn, op1_slfi, op2_slfi, &r1, &i2)) - pv_add_constant (&data->gpr[r1], -((CORE_ADDR)i2 & 0xffffffff)); - - /* SLGFI r1, i2 --- subtract logical immediate (64-bit version) */ - else if (word_size == 8 - && is_ril (insn, op1_slgfi, op2_slgfi, &r1, &i2)) - pv_add_constant (&data->gpr[r1], -((CORE_ADDR)i2 & 0xffffffff)); - - /* SR r1, r2 -- subtract register */ - else if (word_size == 4 - && is_rr (insn, op_sr, &r1, &r2)) - pv_subtract (&data->gpr[r1], &data->gpr[r1], &data->gpr[r2]); - - /* SGR r1, r2 -- subtract register (64-bit version) */ - else if (word_size == 8 - && is_rre (insn, op_sgr, &r1, &r2)) - pv_subtract (&data->gpr[r1], &data->gpr[r1], &data->gpr[r2]); - - /* S r1, d2(x2, b2) -- subtract */ - else if (word_size == 4 - && is_rx (insn, op_s, &r1, &d2, &x2, &b2)) - { - struct prologue_value addr; - struct prologue_value value; - - compute_x_addr (&addr, data->gpr, d2, x2, b2); - s390_load (&addr, 4, &value, data); - - pv_subtract (&data->gpr[r1], &data->gpr[r1], &value); - } - - /* SY r1, d2(x2, b2) -- subtract (long-displacement version) */ - else if (word_size == 4 - && is_rxy (insn, op1_sy, op2_sy, &r1, &d2, &x2, &b2)) - { - struct prologue_value addr; - struct prologue_value value; - - compute_x_addr (&addr, data->gpr, d2, x2, b2); - s390_load (&addr, 4, &value, data); - - pv_subtract (&data->gpr[r1], &data->gpr[r1], &value); - } - - /* SG r1, d2(x2, b2) -- subtract (64-bit version) */ - else if (word_size == 8 - && is_rxy (insn, op1_sg, op2_sg, &r1, &d2, &x2, &b2)) - { - struct prologue_value addr; - struct prologue_value value; - - compute_x_addr (&addr, data->gpr, d2, x2, b2); - s390_load (&addr, 8, &value, data); - - pv_subtract (&data->gpr[r1], &data->gpr[r1], &value); - } - - /* NR r1, r2 --- logical and */ - else if (word_size == 4 - && is_rr (insn, op_nr, &r1, &r2)) - pv_logical_and (&data->gpr[r1], &data->gpr[r1], &data->gpr[r2]); - - /* NGR r1, r2 >--- logical and (64-bit version) */ - else if (word_size == 8 - && is_rre (insn, op_ngr, &r1, &r2)) - pv_logical_and (&data->gpr[r1], &data->gpr[r1], &data->gpr[r2]); - - /* LA r1, d2(x2, b2) --- load address */ - else if (is_rx (insn, op_la, &r1, &d2, &x2, &b2)) - compute_x_addr (&data->gpr[r1], data->gpr, d2, x2, b2); - - /* LAY r1, d2(x2, b2) --- load address (long-displacement version) */ - else if (is_rxy (insn, op1_lay, op2_lay, &r1, &d2, &x2, &b2)) - compute_x_addr (&data->gpr[r1], data->gpr, d2, x2, b2); - - /* LARL r1, i2 --- load address relative long */ + /* AHI r1, i2 --- add halfword immediate. */ + /* AGHI r1, i2 --- add halfword immediate (64-bit version). */ + /* AFI r1, i2 --- add fullword immediate. */ + /* AGFI r1, i2 --- add fullword immediate (64-bit version). */ + else if (is_ri (insn32, op1_ahi, op2_ahi, &r1, &i2) + || is_ri (insn64, op1_aghi, op2_aghi, &r1, &i2) + || is_ril (insn32, op1_afi, op2_afi, &r1, &i2) + || is_ril (insn64, op1_agfi, op2_agfi, &r1, &i2)) + data->gpr[r1] = pv_add_constant (data->gpr[r1], i2); + + /* ALFI r1, i2 --- add logical immediate. */ + /* ALGFI r1, i2 --- add logical immediate (64-bit version). */ + else if (is_ril (insn32, op1_alfi, op2_alfi, &r1, &i2) + || is_ril (insn64, op1_algfi, op2_algfi, &r1, &i2)) + data->gpr[r1] = pv_add_constant (data->gpr[r1], + (CORE_ADDR)i2 & 0xffffffff); + + /* AR r1, r2 -- add register. */ + /* AGR r1, r2 -- add register (64-bit version). */ + else if (is_rr (insn32, op_ar, &r1, &r2) + || is_rre (insn64, op_agr, &r1, &r2)) + data->gpr[r1] = pv_add (data->gpr[r1], data->gpr[r2]); + + /* A r1, d2(x2, b2) -- add. */ + /* AY r1, d2(x2, b2) -- add (long-displacement version). */ + /* AG r1, d2(x2, b2) -- add (64-bit version). */ + else if (is_rx (insn32, op_a, &r1, &d2, &x2, &b2) + || is_rxy (insn32, op1_ay, op2_ay, &r1, &d2, &x2, &b2) + || is_rxy (insn64, op1_ag, op2_ag, &r1, &d2, &x2, &b2)) + data->gpr[r1] = pv_add (data->gpr[r1], + s390_load (data, d2, x2, b2, data->gpr_size)); + + /* SLFI r1, i2 --- subtract logical immediate. */ + /* SLGFI r1, i2 --- subtract logical immediate (64-bit version). */ + else if (is_ril (insn32, op1_slfi, op2_slfi, &r1, &i2) + || is_ril (insn64, op1_slgfi, op2_slgfi, &r1, &i2)) + data->gpr[r1] = pv_add_constant (data->gpr[r1], + -((CORE_ADDR)i2 & 0xffffffff)); + + /* SR r1, r2 -- subtract register. */ + /* SGR r1, r2 -- subtract register (64-bit version). */ + else if (is_rr (insn32, op_sr, &r1, &r2) + || is_rre (insn64, op_sgr, &r1, &r2)) + data->gpr[r1] = pv_subtract (data->gpr[r1], data->gpr[r2]); + + /* S r1, d2(x2, b2) -- subtract. */ + /* SY r1, d2(x2, b2) -- subtract (long-displacement version). */ + /* SG r1, d2(x2, b2) -- subtract (64-bit version). */ + else if (is_rx (insn32, op_s, &r1, &d2, &x2, &b2) + || is_rxy (insn32, op1_sy, op2_sy, &r1, &d2, &x2, &b2) + || is_rxy (insn64, op1_sg, op2_sg, &r1, &d2, &x2, &b2)) + data->gpr[r1] = pv_subtract (data->gpr[r1], + s390_load (data, d2, x2, b2, data->gpr_size)); + + /* LA r1, d2(x2, b2) --- load address. */ + /* LAY r1, d2(x2, b2) --- load address (long-displacement version). */ + else if (is_rx (insn, op_la, &r1, &d2, &x2, &b2) + || is_rxy (insn, op1_lay, op2_lay, &r1, &d2, &x2, &b2)) + data->gpr[r1] = s390_addr (data, d2, x2, b2); + + /* LARL r1, i2 --- load address relative long. */ else if (is_ril (insn, op1_larl, op2_larl, &r1, &i2)) - pv_set_to_constant (&data->gpr[r1], pc + i2 * 2); + data->gpr[r1] = pv_constant (pc + i2 * 2); - /* BASR r1, 0 --- branch and save + /* BASR r1, 0 --- branch and save. Since r2 is zero, this saves the PC in r1, but doesn't branch. */ else if (is_rr (insn, op_basr, &r1, &r2) && r2 == 0) - pv_set_to_constant (&data->gpr[r1], next_pc); + data->gpr[r1] = pv_constant (next_pc); - /* BRAS r1, i2 --- branch relative and save */ + /* BRAS r1, i2 --- branch relative and save. */ else if (is_ri (insn, op1_bras, op2_bras, &r1, &i2)) { - pv_set_to_constant (&data->gpr[r1], next_pc); + data->gpr[r1] = pv_constant (next_pc); next_pc = pc + i2 * 2; /* We'd better not interpret any backward branches. We'll @@ -1636,13 +1109,15 @@ s390_analyze_prologue (struct gdbarch *gdbarch, restore instructions. (The back chain is never restored, just popped.) */ { - struct prologue_value *sp = &data->gpr[S390_SP_REGNUM - S390_R0_REGNUM]; - struct prologue_value *fp = &data->gpr[S390_FRAME_REGNUM - S390_R0_REGNUM]; + pv_t sp = data->gpr[S390_SP_REGNUM - S390_R0_REGNUM]; + pv_t fp = data->gpr[S390_FRAME_REGNUM - S390_R0_REGNUM]; - if ((! pv_is_identical (&pre_insn_sp, sp) - && ! pv_is_register (sp, S390_SP_REGNUM, 0)) - || (! pv_is_identical (&pre_insn_fp, fp) - && ! pv_is_register (fp, S390_FRAME_REGNUM, 0)) + if ((! pv_is_identical (pre_insn_sp, sp) + && ! pv_is_register_k (sp, S390_SP_REGNUM, 0) + && sp.kind != pvk_unknown) + || (! pv_is_identical (pre_insn_fp, fp) + && ! pv_is_register_k (fp, S390_FRAME_REGNUM, 0) + && fp.kind != pvk_unknown) || pre_insn_back_chain_saved_p != data->back_chain_saved_p) result = next_pc; } @@ -1733,8 +1208,8 @@ s390_prologue_frame_unwind_cache (struct frame_info *next_frame, struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); int word_size = gdbarch_ptr_bit (gdbarch) / 8; struct s390_prologue_data data; - struct prologue_value *fp = &data.gpr[S390_FRAME_REGNUM - S390_R0_REGNUM]; - struct prologue_value *sp = &data.gpr[S390_SP_REGNUM - S390_R0_REGNUM]; + pv_t *fp = &data.gpr[S390_FRAME_REGNUM - S390_R0_REGNUM]; + pv_t *sp = &data.gpr[S390_SP_REGNUM - S390_R0_REGNUM]; int i; CORE_ADDR cfa; CORE_ADDR func; @@ -1761,7 +1236,7 @@ s390_prologue_frame_unwind_cache (struct frame_info *next_frame, /* If this was successful, we should have found the instruction that sets the stack pointer register to the previous value of the stack pointer minus the frame size. */ - if (sp->kind != pv_register || sp->reg != S390_SP_REGNUM) + if (!pv_is_register (*sp, S390_SP_REGNUM)) return 0; /* A frame size of zero at this point can mean either a real @@ -1793,11 +1268,10 @@ s390_prologue_frame_unwind_cache (struct frame_info *next_frame, Recognize this case by looking ahead a bit ... */ struct s390_prologue_data data2; - struct prologue_value *sp = &data2.gpr[S390_SP_REGNUM - S390_R0_REGNUM]; + pv_t *sp = &data2.gpr[S390_SP_REGNUM - S390_R0_REGNUM]; if (!(s390_analyze_prologue (gdbarch, func, (CORE_ADDR)-1, &data2) - && sp->kind == pv_register - && sp->reg == S390_SP_REGNUM + && pv_is_register (*sp, S390_SP_REGNUM) && sp->k != 0)) return 0; } @@ -1811,7 +1285,7 @@ s390_prologue_frame_unwind_cache (struct frame_info *next_frame, as the stack pointer, we're probably using it. If it holds some other value -- even a constant offset -- it is most likely used as temp register. */ - if (pv_is_identical (sp, fp)) + if (pv_is_identical (*sp, *fp)) frame_pointer = S390_FRAME_REGNUM; else frame_pointer = S390_SP_REGNUM; -- 2.7.4