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