summaryrefslogtreecommitdiff
path: root/xpcom/reflect/xptcall/md/unix/xptcinvoke_asm_ipf64.s
blob: 140c441177b923ae3eac8874fe074f7d97f949ff (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146

// Select C numeric constant
        .radix  C
// for 64 bit mode, use .psr abi64
        .psr    abi64
// little endian
        .psr    lsb
// Section has executable code
        .section .text, "ax","progbits"
// procedure named 'NS_InvokeByIndex'
        .proc   NS_InvokeByIndex
// manual bundling
        .explicit

// extern "C" uint32_t
// invoke_copy_to_stack(uint64_t* d,
//   const uint32_t paramCount, nsXPTCVariant* s)
        .global invoke_copy_to_stack
//      .exclass  invoke_copy_to_stack, @fullyvisible
        .type   invoke_copy_to_stack,@function

//      .exclass  NS_InvokeByIndex, @fullyvisible
        .type   NS_InvokeByIndex,@function

// XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
//   uint32_t paramCount, nsXPTCVariant* params);
NS_InvokeByIndex::
        .prologue
        .save ar.pfs, r37
// allocate 4 input args, 6 local args, and 8 output args
        alloc           r37 = ar.pfs, 4, 6, 8, 0   // M
        nop.i           0                       ;; // I

// unwind table already knows gp, no need to specify anything
        add             r39 = 0, gp                // A
        .save rp, r36
        mov             r36 = rp                   // I
        .vframe r38
        add             r38 = 0, sp             ;; // A

// We first calculate the amount of extra memory stack space required
// for the arguments, and register storage.
// We then call invoke_copy_to_stack() to write the argument contents
// to the specified memory regions.
// We then copy the integer arguments to integer registers, and floating
// arguments to float registers.
// Lastly we load the virtual table jump pointer, and call the target
// subroutine.

// in0 : that
// in1 : methodIndex
// in2 : paramCount
// in3 : params

// stack frame size is 16 + (8 * even(paramCount)) + 64 + 64
// 16 byte frame header
// 8 * even(paramCount) memory argument area
// 64 bytes integer register area
// 64 bytes float register area
// This scheme makes sure stack fram size is a multiple of 16

        .body
        add             r10 = 8, r0          // A
// r41 points to float register area
        add             r41 = -64, sp        // A
// r40 points to int register area
        add             r40 = -128, sp    ;; // A

        add             out1 = 0, r40        // A
        add             out2 = 0, r41        // A
        tbit.z          p14,p15 = in2,0   ;; // I

// compute 8 * even(paramCount)
(p14)   shladd          r11 = in2, 3, r0  ;; // A
(p15)   shladd          r11 = in2, 3, r10 ;; // A
        sub             out0 = r40, r11   ;; // A

// advance the stack frame
        add             sp = -16, out0       // A
        add             out3 = 0, in2        // A
        add             out4 = 0, in3        // A

// branch to invoke_copy_to_stack
        br.call.sptk.few rp = invoke_copy_to_stack ;; // B

// restore gp
        add             gp = 0, r39          // A
        add             out0 = 0, in0        // A

// load the integer and float registers
        ld8             out1 = [r40], 8      // M
        ldfd            f8 = [r41], 8       ;; // M

        ld8             out2 = [r40], 8      // M
        ldfd            f9 = [r41], 8       ;; // M

        ld8             out3 = [r40], 8      // M
        ldfd            f10 = [r41], 8      ;; // M

        ld8             out4 = [r40], 8      // M
        ldfd            f11 = [r41], 8      ;; // M

        ld8             out5 = [r40], 8      // M
        ldfd            f12 = [r41], 8      ;; // M
// 16 * methodIndex
        shladd          r11 = in1, 4, r0     // A

        ld8             out6 = [r40], 8      // M
        ldfd            f13 = [r41], 8      ;; // M

        ld8             out7 = [r40], 8      // M
        ldfd            f14 = [r41], 8       // M
        add             r8 = 0, in0       ;; // A

// look up virtual base table and dispatch to target subroutine
// This section assumes 64 bit pointer mode, and virtual base table
// layout from the ABI http://www.codesourcery.com/cxx-abi/abi.html

// load base table
        ld8             r8 = [r8]         ;; // M
        add             r8 = r11, r8      ;; // A

 // first entry is jump pointer, second entry is gp
        add             r9 = 8, r8       ;; // A
// load jump pointer
        ld8             r8 = [r8]

// load gp
        ld8             gp = [r9]        ;; // M
        mov             b6 = r8          ;; // I

// branch to target virtual function
        br.call.sptk.few rp = b6          ;; // B

// epilog
        mov             ar.pfs = r37         // I
        mov             rp = r36          ;; // I

        add             sp = 0, r38          // A
        add             gp = 0, r39          // A
        br.ret.sptk.few rp                ;; // B

        .endp

/* Magic indicating no need for an executable stack */
.section .note.GNU-stack, "", @progbits ; .previous