summaryrefslogtreecommitdiffstats
path: root/xpcom/reflect/xptcall/md/unix/xptcinvoke_linux_alpha.cpp
blob: dc111e435879ddbc6a0d571b973f930a7755a996 (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
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/* Platform specific code to invoke XPCOM methods on native objects */

#include "xptcprivate.h"

/* Prototype specifies unmangled function name and disables unused warning */
static void
invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s)
__asm__("invoke_copy_to_stack") __attribute__((used));

static void
invoke_copy_to_stack(uint64_t* d, uint32_t paramCount, nsXPTCVariant* s)
{
    const uint8_t NUM_ARG_REGS = 6-1;        // -1 for "this" pointer

    for(uint32_t i = 0; i < paramCount; i++, d++, s++)
    {
        if(s->IsPtrData())
        {
            *d = (uint64_t)s->ptr;
            continue;
        }
        switch(s->type)
        {
        case nsXPTType::T_I8     : *d = (uint64_t)s->val.i8;     break;
        case nsXPTType::T_I16    : *d = (uint64_t)s->val.i16;    break;
        case nsXPTType::T_I32    : *d = (uint64_t)s->val.i32;    break;
        case nsXPTType::T_I64    : *d = (uint64_t)s->val.i64;    break;
        case nsXPTType::T_U8     : *d = (uint64_t)s->val.u8;     break;
        case nsXPTType::T_U16    : *d = (uint64_t)s->val.u16;    break;
        case nsXPTType::T_U32    : *d = (uint64_t)s->val.u32;    break;
        case nsXPTType::T_U64    : *d = (uint64_t)s->val.u64;    break;
        case nsXPTType::T_FLOAT  :
            if(i < NUM_ARG_REGS)
            {
                // convert floats to doubles if they are to be passed
                // via registers so we can just deal with doubles later
                union { uint64_t u64; double d; } t;
                t.d = (double)s->val.f;
                *d = t.u64;
            }
            else
                // otherwise copy to stack normally
                *d = (uint64_t)s->val.u32;
            break;
        case nsXPTType::T_DOUBLE : *d = (uint64_t)s->val.u64;    break;
        case nsXPTType::T_BOOL   : *d = (uint64_t)s->val.b;      break;
        case nsXPTType::T_CHAR   : *d = (uint64_t)s->val.c;      break;
        case nsXPTType::T_WCHAR  : *d = (uint64_t)s->val.wc;     break;
        default:
            // all the others are plain pointer types
            *d = (uint64_t)s->val.p;
            break;
        }
    }
}

/*
 * EXPORT_XPCOM_API(nsresult)
 * NS_InvokeByIndex(nsISupports* that, uint32_t methodIndex,
 *                  uint32_t paramCount, nsXPTCVariant* params)
 */
__asm__(
    "#### NS_InvokeByIndex ####\n"
".text\n\t"
    ".align 5\n\t"
    ".globl NS_InvokeByIndex\n\t"
    ".ent NS_InvokeByIndex\n"
"NS_InvokeByIndex:\n\t"
    ".frame $15,32,$26,0\n\t"
    ".mask 0x4008000,-32\n\t"
    "ldgp $29,0($27)\n"
"$NS_InvokeByIndex..ng:\n\t"
    "subq $30,32,$30\n\t"
    "stq $26,0($30)\n\t"
    "stq $15,8($30)\n\t"
    "bis $30,$30,$15\n\t"
    ".prologue 1\n\t"

    /*
     * Allocate enough stack space to hold the greater of 6 or "paramCount"+1
     * parameters. (+1 for "this" pointer)  Room for at least 6 parameters
     * is required for storage of those passed via registers.
     */

    "bis $31,5,$2\n\t"      /* count = MAX(5, "paramCount") */
    "cmplt $2,$18,$1\n\t"
    "cmovne $1,$18,$2\n\t"
    "s8addq $2,16,$1\n\t"   /* room for count+1 params (8 bytes each) */
    "bic $1,15,$1\n\t"      /* stack space is rounded up to 0 % 16 */
    "subq $30,$1,$30\n\t"

    "stq $16,0($30)\n\t"    /* save "that" (as "this" pointer) */
    "stq $17,16($15)\n\t"   /* save "methodIndex" */

    "addq $30,8,$16\n\t"    /* pass stack pointer */
    "bis $18,$18,$17\n\t"   /* pass "paramCount" */
    "bis $19,$19,$18\n\t"   /* pass "params" */
    "bsr $26,$invoke_copy_to_stack..ng\n\t"     /* call invoke_copy_to_stack */

    /*
     * Copy the first 6 parameters to registers and remove from stack frame.
     * Both the integer and floating point registers are set for each parameter
     * except the first which is the "this" pointer.  (integer only)
     * The floating point registers are all set as doubles since the
     * invoke_copy_to_stack function should have converted the floats.
     */
    "ldq $16,0($30)\n\t"    /* integer registers */
    "ldq $17,8($30)\n\t"
    "ldq $18,16($30)\n\t"
    "ldq $19,24($30)\n\t"
    "ldq $20,32($30)\n\t"
    "ldq $21,40($30)\n\t"
    "ldt $f17,8($30)\n\t"   /* floating point registers */
    "ldt $f18,16($30)\n\t"
    "ldt $f19,24($30)\n\t"
    "ldt $f20,32($30)\n\t"
    "ldt $f21,40($30)\n\t"

    "addq $30,48,$30\n\t"   /* remove params from stack */

    /*
     * Call the virtual function with the constructed stack frame.
     */
    "bis $16,$16,$1\n\t"    /* load "this" */
    "ldq $2,16($15)\n\t"    /* load "methodIndex" */
    "ldq $1,0($1)\n\t"      /* load vtable */
    "s8addq $2,$31,$2\n\t"  /* vtable index = "methodIndex" * 8 */
    "addq $1,$2,$1\n\t"
    "ldq $27,0($1)\n\t"     /* load address of function */
    "jsr $26,($27),0\n\t"   /* call virtual function */
    "ldgp $29,0($26)\n\t"

    "bis $15,$15,$30\n\t"
    "ldq $26,0($30)\n\t"
    "ldq $15,8($30)\n\t"
    "addq $30,32,$30\n\t"
    "ret $31,($26),1\n\t"
    ".end NS_InvokeByIndex"
    );