+ if (AM33_MODE (gdbarch) == 2)
+ {
+ /* Determine if any floating point registers are to be saved.
+ Look for one of the following three prologue formats:
+
+ [movm [regs],(sp)] [movm [regs],(sp)] [movm [regs],(sp)]
+
+ add -SIZE,sp add -SIZE,sp add -SIZE,sp
+ fmov fs#,(sp) mov sp,a0/a1 mov sp,a0/a1
+ fmov fs#,(#,sp) fmov fs#,(a0/a1+) add SIZE2,a0/a1
+ ... ... fmov fs#,(a0/a1+)
+ ... ... ...
+ fmov fs#,(#,sp) fmov fs#,(a0/a1+) fmov fs#,(a0/a1+)
+
+ [mov sp,a3] [mov sp,a3]
+ [add -SIZE2,sp] [add -SIZE2,sp] */
+
+ /* Remember the address at which we started in the event that we
+ don't ultimately find an fmov instruction. Once we're certain
+ that we matched one of the above patterns, we'll set
+ ``restore_addr'' to the appropriate value. Note: At one time
+ in the past, this code attempted to not adjust ``addr'' until
+ there was a fair degree of certainty that the pattern would be
+ matched. However, that code did not wait until an fmov instruction
+ was actually encountered. As a consequence, ``addr'' would
+ sometimes be advanced even when no fmov instructions were found. */
+ CORE_ADDR restore_addr = addr;
+ int fmov_found = 0;
+
+ /* First, look for add -SIZE,sp (i.e. add imm8,sp (0xf8feXX)
+ or add imm16,sp (0xfafeXXXX)
+ or add imm32,sp (0xfcfeXXXXXXXX)) */
+ imm_size = 0;
+ if (buf[0] == 0xf8 && buf[1] == 0xfe)
+ imm_size = 1;
+ else if (buf[0] == 0xfa && buf[1] == 0xfe)
+ imm_size = 2;
+ else if (buf[0] == 0xfc && buf[1] == 0xfe)
+ imm_size = 4;
+ if (imm_size != 0)
+ {
+ /* 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. 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;
+
+ /* An fmov instruction has just been seen. We can
+ now really commit to the pattern match. */
+
+ fmov_found = 1;
+
+ /* 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;
+ }
+ }
+ }
+ }
+ /* If no fmov instructions were found by the above sequence, reset
+ the state and pretend that the above bit of code never happened. */
+ if (!fmov_found)
+ {
+ addr = restore_addr;
+ status = target_read_memory (addr, buf, 2);
+ if (status != 0)
+ goto finish_prologue;
+ stack_extra_size = 0;
+ }
+ }
+