Abstract immediate loading on x86-64.
[sbcl.git] / src / runtime / arm64-arch.c
blobb6a144b2f987de0bb2849f0cf3eaa29c2afda75f
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"
26 #include "pseudo-atomic.h"
28 void arch_init(void)
30 return;
33 os_vm_address_t arch_get_bad_addr(int sig, siginfo_t *code, os_context_t *context)
35 return (os_vm_address_t)code->si_addr;
38 void arch_skip_instruction(os_context_t *context)
40 /* KLUDGE: Other platforms check for trap codes and skip inlined
41 * trap/error parameters. We should too. */
43 /* Note that we're doing integer arithmetic here, not pointer. So
44 * the value that the return value of os_context_pc_addr() points
45 * to will be incremented by 4, not 32.
47 *os_context_pc_addr(context) += 4;
50 unsigned char *arch_internal_error_arguments(os_context_t *context)
52 return (unsigned char *)*os_context_pc_addr(context);
55 boolean arch_pseudo_atomic_atomic(os_context_t *context)
57 /* FIXME: this foreign_function_call_active test is dubious at
58 * best. If a foreign call is made in a pseudo atomic section
59 * (?) or more likely a pseudo atomic section is in a foreign
60 * call then an interrupt is executed immediately. Maybe it
61 * has to do with C code not maintaining pseudo atomic
62 * properly. MG - 2005-08-10
64 * The foreign_function_call_active used to live at each call-site
65 * to arch_pseudo_atomic_atomic, but this seems clearer.
66 * --NS 2007-05-15 */
67 #ifdef LISP_FEATURE_GENCGC
68 return get_pseudo_atomic_atomic(arch_os_get_current_thread());
69 #else
70 return (!foreign_function_call_active)
71 && (NIL != SymbolValue(PSEUDO_ATOMIC_ATOMIC,0));
72 #endif
75 void arch_set_pseudo_atomic_interrupted(os_context_t *context)
77 set_pseudo_atomic_interrupted(arch_os_get_current_thread());
80 void arch_clear_pseudo_atomic_interrupted(os_context_t *context)
82 clear_pseudo_atomic_interrupted(arch_os_get_current_thread());
85 unsigned int arch_install_breakpoint(void *pc)
87 /* FIXME: Implement. */
89 return 0;
92 void arch_remove_breakpoint(void *pc, unsigned int orig_inst)
94 /* FIXME: Implement. */
97 void arch_do_displaced_inst(os_context_t *context, unsigned int orig_inst)
99 /* FIXME: Implement. */
102 void
103 arch_handle_breakpoint(os_context_t *context)
105 handle_breakpoint(context);
108 void
109 arch_handle_fun_end_breakpoint(os_context_t *context)
111 *os_context_pc_addr(context) = (int) handle_fun_end_breakpoint(context);
114 void
115 arch_handle_single_step_trap(os_context_t *context, int trap)
117 unsigned char register_offset =
118 *((unsigned char *)(*os_context_pc_addr(context))+5);
119 handle_single_step_trap(context, trap, register_offset);
120 /* KLUDGE: arch_skip_instruction() only skips one instruction, and
121 * there is a following word to deal with as well, so skip
122 * twice. */
123 arch_skip_instruction(context);
124 arch_skip_instruction(context);
127 static void
128 sigtrap_handler(int signal, siginfo_t *siginfo, os_context_t *context)
130 u32 trap_instruction = *((u32 *)*os_context_pc_addr(context));
131 unsigned code = trap_instruction >> 5 & 0xFF;
132 if ((trap_instruction >> 21) != 0x6A1) {
133 lose("Unrecognized trap instruction %08lx in sigtrap_handler() (PC: %p)",
134 trap_instruction, *os_context_pc_addr(context));
137 handle_trap(context, code);
140 void arch_install_interrupt_handlers()
142 undoably_install_low_level_interrupt_handler(SIGTRAP, sigtrap_handler);
146 #ifdef LISP_FEATURE_LINKAGE_TABLE
148 /* Linkage tables
150 * Linkage entry size is 16, because we need 2 instructions and an 8 byte address.
153 #define LINKAGE_TEMP_REG reg_NFP
155 void arch_write_linkage_table_jmp(char *reloc_addr, void *target_addr)
158 ldr reg,=address
159 br reg
160 address
162 int* inst_ptr;
163 unsigned inst;
165 inst_ptr = (int*) reloc_addr;
167 // ldr reg, =address
168 inst = 0x58000000 | 2 << 5 | LINKAGE_TEMP_REG;
169 *inst_ptr++ = inst;
171 // br reg
172 inst = 0xD61F0000 | LINKAGE_TEMP_REG << 5;
173 *inst_ptr++ = inst;
175 // address
176 *(unsigned long *)inst_ptr++ = target_addr;
178 os_flush_icache((os_vm_address_t) reloc_addr, (char*) inst_ptr - reloc_addr);
181 void
182 arch_write_linkage_table_ref(void * reloc_addr, void *target_addr)
184 *(unsigned long *)reloc_addr = (unsigned long)target_addr;
187 #endif