]> gitweb.factorcode.org Git - factor.git/blob - vm/cpu-ppc.hpp
scryfall: better moxfield words
[factor.git] / vm / cpu-ppc.hpp
1 namespace factor {
2
3 #ifdef FACTOR_64
4 #define FACTOR_CPU_STRING "ppc.64"
5 #else
6 #define FACTOR_CPU_STRING "ppc.32"
7 #endif
8
9 #define CALLSTACK_BOTTOM(ctx) (ctx->callstack_seg->end - 32)
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 one instruction.
18 static const fixnum xt_tail_pic_offset = 4;
19
20 inline static void check_call_site(cell return_address) {
21   uint32_t insn = *(uint32_t*)return_address;
22   // Check that absolute bit is 0
23   FACTOR_ASSERT((insn & 0x2) == 0x0);
24   // Check that instruction is branch
25   FACTOR_ASSERT((insn >> 26) == 0x12);
26 }
27
28 static const uint32_t b_mask = 0x3fffffc;
29
30 inline static void* get_call_target(cell return_address) {
31   return_address -= 4;
32   check_call_site(return_address);
33
34   uint32_t insn = *(uint32_t*)return_address;
35   uint32_t unsigned_addr = (insn & b_mask);
36   int32_t signed_addr = (int32_t)(unsigned_addr << 6) >> 6;
37   return (void*)(signed_addr + return_address);
38 }
39
40 inline static void set_call_target(cell return_address, cell target) {
41   return_address -= 4;
42   check_call_site(return_address);
43
44   uint32_t insn = *(uint32_t*)return_address;
45
46   fixnum relative_address = target - return_address;
47   insn = ((insn & ~b_mask) | (relative_address & b_mask));
48   *(uint32_t*)return_address = insn;
49
50   // Flush the cache line containing the call we just patched
51   __asm__ __volatile__("icbi 0, %0\n"
52                        "sync\n" ::"r"(return_address)
53                        :);
54 }
55
56 inline static bool tail_call_site_p(cell return_address) {
57   return_address -= 4;
58   uint32_t insn = *(uint32_t*)return_address;
59   return (insn & 0x1) == 0;
60 }
61
62 inline static unsigned int fpu_status(unsigned int status) {
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 }