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