- /* An "add -#,sp" instruction has been found. "addr + 2 + imm_size"
- is the address of the next instruction. Don't modify "addr" until
- the next "floating point prologue" instruction is found. If this
- is not a prologue that saves floating point registers we need to
- be able to back out of this bit of code and continue with the
- prologue analysis. */
- if (addr + 2 + imm_size < stop)
- {
- if (!safe_frame_unwind_memory (fi, addr + 2 + imm_size, buf, 3))
- goto finish_prologue;
- if ((buf[0] & 0xfc) == 0x3c)
- {
- /* Occasionally, especially with C++ code, the "fmov"
- instructions will be preceded by "mov sp,aN"
- (aN => a0, a1, a2, or a3).
-
- This is a one byte instruction: mov sp,aN = 0011 11XX
- where XX is the register number.
-
- Skip this instruction by incrementing addr. (We're
- committed now.) The "fmov" instructions will have the
- form "fmov fs#,(aN+)" in this case, but that will not
- necessitate a change in the "fmov" parsing logic below. */
-
- addr++;
-
- if ((buf[1] & 0xfc) == 0x20)
- {
- /* Occasionally, especially with C++ code compiled with
- the -fomit-frame-pointer or -O3 options, the
- "mov sp,aN" instruction will be followed by an
- "add #,aN" instruction. This indicates the
- "stack_size", the size of the portion of the stack
- containing the arguments. This instruction format is:
- add #,aN = 0010 00XX YYYY YYYY
- where XX is the register number
- YYYY YYYY is the constant.
- Note the size of the stack (as a negative number) in
- the frame info structure. */
- if (fi)
- stack_extra_size += -buf[2];
-
- addr += 2;
- }
- }
-
- if ((buf[0] & 0xfc) == 0x3c ||
- buf[0] == 0xf9 || buf[0] == 0xfb)
- {
- /* An "fmov" instruction has been found indicating that this
- prologue saves floating point registers (or, as described
- above, a "mov sp,aN" and possible "add #,aN" have been
- found and we will assume an "fmov" follows). Process the
- consecutive "fmov" instructions. */
- for (addr += 2 + imm_size;;addr += imm_size)
- {
- int regnum;
-
- /* Read the "fmov" instruction. */
- if (addr >= stop ||
- !safe_frame_unwind_memory (fi, addr, buf, 4))
- goto finish_prologue;
-
- if (buf[0] != 0xf9 && buf[0] != 0xfb)
- break;
-
- /* Get the floating point register number from the
- 2nd and 3rd bytes of the "fmov" instruction:
- Machine Code: 0000 00X0 YYYY 0000 =>
- Regnum: 000X YYYY */
- regnum = (buf[1] & 0x02) << 3;
- regnum |= ((buf[2] & 0xf0) >> 4) & 0x0f;
-
- /* Add this register number to the bit mask of floating
- point registers that have been saved. */
- fpregmask |= 1 << regnum;
-
- /* Determine the length of this "fmov" instruction.
- fmov fs#,(sp) => 3 byte instruction
- fmov fs#,(#,sp) => 4 byte instruction */
- imm_size = (buf[0] == 0xf9) ? 3 : 4;
- }
- }
- else
- {
- /* No "fmov" was found. Reread the two bytes at the original
- "addr" to reset the state. */
- if (!safe_frame_unwind_memory (fi, addr, buf, 2))
- goto finish_prologue;
- }
- }
- /* else the prologue consists entirely of an "add -SIZE,sp"
- instruction. Handle this below. */