]> gitweb.factorcode.org Git - factor.git/blob - vm/cpu-ppc.hpp
Merge branch 'master' into eliminating_register_variables
[factor.git] / vm / cpu-ppc.hpp
1 namespace factor
2 {
3
4 #define FACTOR_CPU_STRING "ppc"
5 #define VM_ASM_API VM_C_API
6
7 /* In the instruction sequence:
8
9    LOAD32 r3,...
10    B blah
11
12    the offset from the immediate operand to LOAD32 to the instruction after
13    the branch is two instructions. */
14 static const fixnum xt_tail_pic_offset = 4 * 2;
15
16 inline static void check_call_site(cell return_address)
17 {
18 #ifdef FACTOR_DEBUG
19         cell insn = *(cell *)return_address;
20         /* Check that absolute bit is 0 */
21         assert((insn & 0x2) == 0x0);
22         /* Check that instruction is branch */
23         assert((insn >> 26) == 0x12);
24 #endif
25 }
26
27 static const cell b_mask = 0x3fffffc;
28
29 inline static void *get_call_target(cell return_address)
30 {
31         return_address -= sizeof(cell);
32         check_call_site(return_address);
33
34         cell insn = *(cell *)return_address;
35         cell unsigned_addr = (insn & b_mask);
36         fixnum signed_addr = (fixnum)(unsigned_addr << 6) >> 6;
37         return (void *)(signed_addr + return_address);
38 }
39
40 inline static void set_call_target(cell return_address, void *target)
41 {
42         return_address -= sizeof(cell);
43         check_call_site(return_address);
44
45         cell insn = *(cell *)return_address;
46
47         fixnum relative_address = ((cell)target - return_address);
48         insn = ((insn & ~b_mask) | (relative_address & b_mask));
49         *(cell *)return_address = insn;
50
51         /* Flush the cache line containing the call we just patched */
52         __asm__ __volatile__ ("icbi 0, %0\n" "sync\n"::"r" (return_address):);
53 }
54
55 inline static bool tail_call_site_p(cell return_address)
56 {
57         return_address -= sizeof(cell);
58         cell insn = *(cell *)return_address;
59         return (insn & 0x1) == 0;
60 }
61
62 inline static unsigned int fpu_status(unsigned int status)
63 {
64         unsigned int r = 0;
65
66         if (status & 0x20000000)
67                 r |= FP_TRAP_INVALID_OPERATION;
68         if (status & 0x10000000)
69                 r |= FP_TRAP_OVERFLOW;
70         if (status & 0x08000000)
71                 r |= FP_TRAP_UNDERFLOW;
72         if (status & 0x04000000)
73                 r |= FP_TRAP_ZERO_DIVIDE;
74         if (status & 0x02000000)
75                 r |= FP_TRAP_INEXACT;
76
77         return r;
78 }
79
80 /* Defined in assembly */
81 VM_C_API void c_to_factor(cell quot, void *vm);
82 VM_C_API void throw_impl(cell quot, void *new_stack, void *vm);
83 VM_C_API void lazy_jit_compile(cell quot, void *vm);
84 VM_C_API void flush_icache(cell start, cell len);
85
86 VM_C_API void set_callstack(
87         void *vm,
88         stack_frame *to,
89         stack_frame *from,
90         cell length,
91         void *(*memcpy)(void*,const void*, size_t));
92
93 }