Optimize load/store pairs on ARM64.
[sbcl.git] / src / runtime / arm-arch.c
blob66655a8cc25410759fa370a175c89c872ca34f72
1 /*
2 * This software is part of the SBCL system. See the README file for
3 * more information.
5 * This software is derived from the CMU CL system, which was
6 * written at Carnegie Mellon University and released into the
7 * public domain. The software is in the public domain and is
8 * provided with absolutely no warranty. See the COPYING and CREDITS
9 * files for more information.
11 #include <stdio.h>
13 #include "sbcl.h"
14 #include "runtime.h"
15 #include "arch.h"
16 #include "globals.h"
17 #include "validate.h"
18 #include "os.h"
19 #include "lispregs.h"
20 #include "signal.h"
21 #include "alloc.h"
22 #include "interrupt.h"
23 #include "interr.h"
24 #include "breakpoint.h"
25 #include "monitor.h"
27 void arch_init(void)
29 return;
32 os_vm_address_t arch_get_bad_addr(int sig, siginfo_t *code, os_context_t *context)
34 return (os_vm_address_t)code->si_addr;
37 void arch_skip_instruction(os_context_t *context)
39 /* KLUDGE: Other platforms check for trap codes and skip inlined
40 * trap/error parameters. We should too. */
42 /* Note that we're doing integer arithmetic here, not pointer. So
43 * the value that the return value of os_context_pc_addr() points
44 * to will be incremented by 4, not 16.
46 *os_context_pc_addr(context) += 4;
49 unsigned char *arch_internal_error_arguments(os_context_t *context)
51 return (unsigned char *)(*os_context_pc_addr(context) + 5);
54 boolean arch_pseudo_atomic_atomic(os_context_t *context)
56 /* FIXME: this foreign_function_call_active test is dubious at
57 * best. If a foreign call is made in a pseudo atomic section
58 * (?) or more likely a pseudo atomic section is in a foreign
59 * call then an interrupt is executed immediately. Maybe it
60 * has to do with C code not maintaining pseudo atomic
61 * properly. MG - 2005-08-10
63 * The foreign_function_call_active used to live at each call-site
64 * to arch_pseudo_atomic_atomic, but this seems clearer.
65 * --NS 2007-05-15 */
66 #ifdef LISP_FEATURE_GENCGC
67 return SymbolValue(PSEUDO_ATOMIC_ATOMIC, 0) != NIL;
68 #else
69 return (!foreign_function_call_active)
70 && (NIL != SymbolValue(PSEUDO_ATOMIC_ATOMIC,0));
71 #endif
74 void arch_set_pseudo_atomic_interrupted(os_context_t *context)
76 SetSymbolValue(PSEUDO_ATOMIC_INTERRUPTED, do_pending_interrupt, 0);
79 void arch_clear_pseudo_atomic_interrupted(os_context_t *context)
81 SetSymbolValue(PSEUDO_ATOMIC_INTERRUPTED, 0, 0);
84 unsigned int arch_install_breakpoint(void *pc)
86 /* FIXME: Implement. */
88 return 0;
91 void arch_remove_breakpoint(void *pc, unsigned int orig_inst)
93 /* FIXME: Implement. */
96 void arch_do_displaced_inst(os_context_t *context, unsigned int orig_inst)
98 /* FIXME: Implement. */
101 void
102 arch_handle_breakpoint(os_context_t *context)
104 handle_breakpoint(context);
107 void
108 arch_handle_fun_end_breakpoint(os_context_t *context)
110 *os_context_pc_addr(context) = (int) handle_fun_end_breakpoint(context);
113 void
114 arch_handle_single_step_trap(os_context_t *context, int trap)
116 unsigned char register_offset =
117 *((unsigned char *)(*os_context_pc_addr(context))+5);
118 handle_single_step_trap(context, trap, register_offset);
119 /* KLUDGE: arch_skip_instruction() only skips one instruction, and
120 * there is a following word to deal with as well, so skip
121 * twice. */
122 arch_skip_instruction(context);
123 arch_skip_instruction(context);
128 #ifdef LISP_FEATURE_LINKAGE_TABLE
130 /* Linkage tables
132 * Linkage entry size is 16, because we need 4 instructions.
135 #define LINKAGE_TEMP_REG reg_NFP
137 void arch_write_linkage_table_jmp(char *reloc_addr, void *target_addr)
140 ldr reg, [pc, #4]
141 bx reg
143 address
145 BX is needed for thumb interworking, without it it could take just two words with
146 ldr pc, [pc, #-4]
147 address
149 int* inst_ptr;
150 unsigned inst;
152 inst_ptr = (int*) reloc_addr;
154 // ldr reg, [pc, #4]
155 inst = 0xe59f0000 | LINKAGE_TEMP_REG << 12 | 4;
156 *inst_ptr++ = inst;
158 // bx reg
159 inst = 0xe12fff10 | LINKAGE_TEMP_REG;
160 *inst_ptr++ = inst;
162 // nop aka mov r0, r0
163 inst = 0xe1a00000;
164 *inst_ptr++ = inst;
166 // address
167 *inst_ptr++ = target_addr;
169 os_flush_icache((os_vm_address_t) reloc_addr, (char*) inst_ptr - reloc_addr);
172 void
173 arch_write_linkage_table_ref(void * reloc_addr, void *target_addr)
175 *(unsigned long *)reloc_addr = (unsigned long)target_addr;
178 #endif