Make `call' command work on arm32. Patch supplied by Richard Earnshaw in

port-arm32/6781.
This commit is contained in:
tv 1999-02-23 23:38:19 +00:00
parent 281bba9355
commit c7452585f3
1 changed files with 64 additions and 58 deletions

View File

@ -24,7 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#define IEEE_FLOAT
#define ADDR_BITS_REMOVE(val) (val)
#define ADDR_BITS_REMOVE(val) ((val) & ~3)
/* Offset from address of function to start of its code.
Zero on most machines. */
@ -342,78 +342,84 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* Push an empty stack frame, to record the current PC, etc. */
#define PUSH_DUMMY_FRAME \
{ \
register CORE_ADDR sp = read_register (SP_REGNUM); \
register int regnum; \
/* opcode for ldmdb fp,{v1-v6,fp,ip,lr,pc}^ */ \
sp = push_word(sp, 0xe92bdbf0); /* dummy return_data_save ins */ \
/* push a pointer to the dummy instruction minus 12 */ \
sp = push_word(sp, read_register (SP_REGNUM) - 16); \
sp = push_word(sp, read_register (PS_REGNUM)); \
sp = push_word(sp, read_register (SP_REGNUM)); \
sp = push_word(sp, read_register (FP_REGNUM)); \
for (regnum = 9; regnum >= 4; regnum --) \
sp = push_word(sp, read_register (regnum)); \
write_register (FP_REGNUM, read_register (SP_REGNUM) - 8); \
write_register (SP_REGNUM, sp); }
#define PUSH_DUMMY_FRAME \
{ \
register CORE_ADDR sp = read_register (SP_REGNUM); \
register int regnum; \
/* opcode for stmdb fp!, {r4-r10, fp, ip, lr, pc} */ \
sp = push_word (sp, 0xe92bdff0); /* dummy return_data_save ins */ \
/* push a pointer to the dummy instruction minus 12 */ \
sp = push_word (sp, read_register (SP_REGNUM) - 16); \
sp = push_word (sp, read_register (PC_REGNUM)); \
sp = push_word (sp, read_register (SP_REGNUM)); \
sp = push_word (sp, read_register (FP_REGNUM)); \
for (regnum = 10; regnum >= 4; regnum--) \
sp = push_word (sp, read_register (regnum)); \
write_register (FP_REGNUM, read_register (SP_REGNUM) - 8); \
write_register (SP_REGNUM, sp); \
}
/* Discard from the stack the innermost frame, restoring all registers. */
#define POP_FRAME \
#define POP_FRAME \
{ \
register CORE_ADDR fp = read_register (FP_REGNUM); \
register unsigned long return_data_save = \
read_memory_integer ( ADDR_BITS_REMOVE(read_memory_integer (fp, 4)) \
- 12, 4); \
register int regnum; \
write_register (PS_REGNUM, read_memory_integer (fp - 4, 4)); \
write_register (PC_REGNUM, ADDR_BITS_REMOVE(read_register (PS_REGNUM))); \
write_register (SP_REGNUM, read_memory_integer (fp - 8, 4)); \
write_register (FP_REGNUM, read_memory_integer (fp - 12, 4)); \
fp -= 12; \
for (regnum = 9; regnum >= 4; regnum--) \
if (return_data_save & (1<<regnum)) { \
fp -= 4; \
write_register (regnum, read_memory_integer(fp, 4)); \
} \
flush_cached_frames (); \
register CORE_ADDR fp = read_register (FP_REGNUM); \
register unsigned long return_data_save = \
read_memory_integer (ADDR_BITS_REMOVE (read_memory_integer (fp, 4)) \
- 12, 4); \
register int regnum; \
write_register (PC_REGNUM, read_memory_integer (fp - 4, 4)); \
write_register (SP_REGNUM, read_memory_integer (fp - 8, 4)); \
write_register (FP_REGNUM, read_memory_integer (fp - 12, 4)); \
fp -= 12; \
for (regnum = 10; regnum >= 4; regnum--) \
if (return_data_save & (1 << regnum)) \
{ \
fp -= 4; \
write_register (regnum, read_memory_integer (fp, 4)); \
} \
flush_cached_frames (); \
}
/* This sequence of words is the instructions
/* This sequence of words is the instructions. We use this rather than bl
becuase the code segment may not be reachable from the stack.
ldmia sp!,{a1-a4}
mov lk,pc
bl *+8
swi bkpt_swi
ldmia sp!, {r0-r3}
mov lr, pc
ldr pc, . + 8
Breakpoint
<address to call>
Note this is 16 bytes. */
Note this is 20 bytes. */
#define CALL_DUMMY {0xe8bd000f, 0xe1a0e00f, 0xeb000000, 0xef180000}
#define CALL_DUMMY {0xe8bd000f, 0xe1a0e00f, 0xe59ff000, 0xe6000011, 0}
#define CALL_DUMMY_START_OFFSET 0 /* Start execution at beginning of dummy */
/* Insert the specified number of args and function address
into a call sequence of the above form stored at DUMMYNAME. */
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
{ \
register enum type_code code = TYPE_CODE (type); \
register nargs_in_registers, struct_return = 0; \
/* fix the load-arguments mask to move the first 4 or less arguments \
into a1-a4 but make sure the structure return address in a1 is \
not disturbed if the function is returning a structure */ \
if ((code == TYPE_CODE_STRUCT || \
code == TYPE_CODE_UNION || \
code == TYPE_CODE_ARRAY) && \
TYPE_LENGTH (type) > 4) { \
nargs_in_registers = min(nargs + 1, 4); \
struct_return = 1; \
} else \
nargs_in_registers = min(nargs, 4); \
*(char *) dummyname = (1 << nargs_in_registers) - 1 - struct_return; \
*(int *)((char *) dummyname + 8) = \
(((fun - (pc + 16)) / 4) & 0x00ffffff) | 0xeb000000; }
#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
{ \
register enum type_code code = TYPE_CODE (type); \
register nargs_in_registers, struct_return = 0; \
/* fix the load-arguments mask to move the first 4 or less arguments \
into a1-a4 but make sure the structure return address in a1 is \
not disturbed if the function is returning a structure */ \
if ((code == TYPE_CODE_STRUCT \
|| code == TYPE_CODE_UNION \
|| code == TYPE_CODE_ARRAY) \
&& TYPE_LENGTH (type) > 4) \
{ \
nargs_in_registers = min(nargs + 1, 4); \
struct_return = 1; \
} \
else \
nargs_in_registers = min(nargs, 4); \
*(char *) dummyname = (1 << nargs_in_registers) - 1 - struct_return; \
*(int *)((char *) dummyname + 16) = fun; \
}
CORE_ADDR arm_get_next_pc PARAMS ((CORE_ADDR));