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