View difference between Paste ID: MwiCVYNd and YYpgrzYU
SHOW: | | - or go back to the newest paste.
1
CPU2/CPU3 bootup code: sub_FFF2EC68
2
CPU1 entrypoint: 0x1FFAE064; CPU2/CPU3 entrypoint at: 0x1FFAE490, 0xFFF2E490
3
4
// CPU2/3 startup routine
5
void sub_FFF2E490()
6
{
7
    int cpu_id;
8
    u32 val;
9
 
10
    __asm__ volatile {
11
        "cpsid aif\nt"
12
    };
13
 
14
    __mrc(0xF, &val, 0xF, 0xC, 0); // Read Performance Monitor Control Register
15
    val |= 0xFFFF00D;
16
    __mcr(0xF, val, 0xF, 0xC, 0);
17
 
18
    0x17E00100 = 1; // Enable interrupts
19
 
20
    cpu_id = __mrc(0xF, 0, 0, 0, 5) & 3;
21
 
22
    /* Tell the CPU0 we are here */
23
    if (cpu_id == 3)
24
        0x10141313 = 1;
25
    else
26
        0x10141312 = 1;
27
 
28
    do {
29
        __wfi();
30
        0x17E00110 = 0x17E0010C; // ack interrupt
31
    } while (0x17E0010C != cpu_id);
32
 
33
    JUMPOUT(0x1FFAE064);
34
}
35
 
36
// a1: enable_SMP?
37
int sub_FFF2EC68(int a1)
38
{
39
    int v1;         // r8@1
40
    signed int v2;      // r10@4
41
    signed int v3;      // r0@16
42
    int v4;         // r0@24
43
    signed int v5;      // r3@25
44
    signed int v6;      // r9@27
45
    unsigned int v7;    // r1@42
46
    int result;     // r0@44
47
    signed int v9;      // r0@47
48
    signed int v10;     // r2@47
49
    signed int v11;     // r1@47
50
    int v12;        // t1@48
51
 
52
    v1 = a1;
53
    if (!a1) {
54
        if ((0x10140FFC & 0b10) >> 1) { // If we have more than 2 CPUs..
55
            if ((0x10140FFC & 0b100) >> 2)  // If 4 CPUs
56
                v2 = 0b101;
57
            else                // If 3 CPUs
58
                v2 = 0b011;
59
 
60
            if ((0x10141300 & 0b111) != v2) {
61
                0x10141304 |= 1; // Power on 3rd ARM11 MPCore
62
                if ((0x10140FFC & 0b100) >> 2) // If 4 CPUs
63
                    0x10141304 |= 0x100; // Power on 4rd ARM11 MPCore
64
 
65
                sub_FFF2E454(0x193);    // delay
66
 
67
                0x17E00100 = 1; // enable interrupts
68
                0x17E01288 = 0x1000000; // Interrupt Pending clear Registers
69
 
70
                0x10141300 = v2 & 0b111 | 0x8000; // enable clk mult, clk=2x, busy=1
71
 
72
                0x17E01458 = 0; // Interrupt Priority Registers
73
                0x17E01858 |= 1;    // Interrupt CPU targets Registers
74
                0x17E01108 = 0x1000000; // Interrupt Enable set Registers ID0-ID31
75
 
76
                do {
77
                    __wfi();
78
                } while (!(0x10141300 & 0x8000)); // While PDN_MPCORE_CLKCNT busy
79
 
80
                0x17E01188 = 0x1000000; //Interrupt Enable set Registers ID32 and upwards
81
 
82
                0x10140400 = 3; // CLK_UNK1
83
            }
84
            0x10140410 = 0x3FFFF; // CLK_UNK2
85
        }
86
 
87
        /* Start shit */
88
        0x1FFFFFF0 = 1;
89
        while (0x1FFFFFF0 != 2) ;
90
        0x1FFFFFF0 = 3;
91
        0x1FFAF405 = 0x1FFFFFF1;
92
        0x1FFAF406 = 0x1FFFFFF2;
93
        if (0x1FFFFFF1 == 3) {
94
            v3 = 0;
95
            do
96
                ++v3;
97
            while (v3 < 0x800000);
98
            0x1FFFFFF0 = 1;
99
            while (0x1FFFFFF0 != 2) ;
100
            0x1FFFFFF0 = 3;
101
        }
102
        /* End shit */
103
 
104
        if ((0x10140FFC & 2) >> 1 && (0x17E00004 & 3) == 3) {   // If we have 4 CPUs
105
            0x17E00008 &= 0xFFFFFF0F;   // SCU power on CPU2 and CPU3
106
 
107
            v4 = 0x10141300 & 0b111;
108
            if ((0x10140FFC & 0b100) >> 2) // If 4 CPUs
109
                v5 = 1;
110
            else
111
                v5 = 2;
112
 
113
            v6 = 1 << v1;
114
            if (v4 != v5) {
115
                0x17E00100 = 1; // enable interrupts
116
                0x17E01288 = 0x1000000;
117
                0x10141300 = v5 & 0b111 | 0x8000; // enable clk mult, clk=1x, busy=1
118
                0x17E01458 = 0;
119
                0x17E01858 |= v6;
120
                0x17E01108 = 0x1000000;
121
                do {
122
                    __wfi();
123
                } while (!(0x10141300 & 0x8000)); // While PDN_MPCORE_CLKCNT busy
124
                0x17E01188 = 0x1000000;
125
            }
126
 
127
            0x10140420 |= 1;        // Enable bootrom overlay
128
            0x10140424 = 0x1FFAE490;    // Set CPU2/3 entrypoint (overlay value)
129
 
130
            if (!(0x10141312 & 0x10)) { // If CPU2 has not booted
131
                0x10141312 |= 2; // Enable CPU2 bootrom data overlay?
132
                0x10141312 |= 1; // Enable CPU2 bootrom instruction overlay
133
            }
134
            if (!(0x10141313 & 0x10)) { // If CPU3 has not booted
135
                0x10141313 |= 2; // Enable CPU3 bootrom data overlay?
136
                0x10141313 |= 1; // Enable CPU3 bootrom instruction overlay
137
            }
138
 
139
            /* Wait until CPU2 is online */
140
            while ((0x10141312 & 0x12) != 0x10)
141
                ;
142
 
143
            /* Wait until CPU3 is online */
144
            while ((0x10141313 & 0x12) != 0x10)
145
                ;
146
 
147
            0x10140420 &= 0xFE; // Disable bootrom overlay
148
 
149
            if (v4 != v5) {
150
                0x17E00100 = 1;
151
                0x17E01288 = 0x1000000;
152
                0x10141300 = v4 & 0b111 | 0x8000; // enable clk mult, clk=orignal state, busy=1
153
                0x17E01458 = 0;
154
                0x17E01858 |= v6;
155
                0x17E01108 = 0x1000000;
156
                do {
157
                    __wfi();
158
                } while (!(0x10141300 & 0x8000));
159
                0x17E01188 = 0x1000000;
160
            }
161
        }
162
        0x1FFFFFDC = 0x1FFAE064; // CPU1 entrypoint
163
    }
164
    v7 = *(_DWORD *) (4 * v1 + 0x1FFAF3C4);
165
    __mcr(15, 0, 0, 8, 7, 0);
166
    __mcr(15, 0, (v7 >> 9 << 9) | 0x12, 2, 0, 0);
167
    __mcr(15, 0, (v7 >> 14 << 14) | 0x12, 2, 0, 1);
168
    __mcr(15, 0, 2u, 2, 0, 2);
169
    __mcr(15, 0, 0, 13, 0, 1);
170
    __mcr(15, 0, 1u, 3, 0, 0);
171
    sub_FFF2E594();
172
 
173
    if (!v1)
174
        0x17E00000 |= 1; // Enable SCU
175
 
176
    // Rest is 3DS shit...
177
 
178
    __mcr(15, 0, __mrc(15, 0, 1, 0, 1) | 0x2F, 1, 0, 1);
179
    result = __mrc(15, 0, 1, 0, 0) | 0xC03805;
180
    __mcr(15, 0, result, 1, 0, 0);
181
    __mcr(15, 0, 0, 7, 5, 4);
182
    __mcr(15, 0, 0, 7, 5, 0);
183
    __mcr(15, 0, 0, 7, 6, 0);
184
    __mcr(15, 0, 0, 8, 7, 0);
185
    __mcr(15, 0, 0, 7, 10, 5);
186
    __mcr(15, 0, 0, 7, 5, 4);
187
    if (!v1) {
188
        *0x1FFAF40C = *0x1FFAF40C & 0xFC6FEBFF | 0x2800000;
189
        *0x1FFAF420 = *0x1FFAF420 & 0xF65FFFE1 | 0x70000001;
190
        *0x1FFAF424 &= 0xFFFFFFFC;
191
        *0x1FFAF410 |= 0x1FFu;
192
        *0x1FFAF418 = 0xFFFF;
193
        while (*0x1FFAF414 & 1) ;
194
        *0x1FFAF414 = 0;
195
        *0x1FFAF408 |= 1u;
196
        v9 = 536821756;
197
        v10 = 536530940;
198
        v11 = 512;
199
        do {
200
            --v11;
201
            *(_DWORD *) (v9 + 4) = *(_DWORD *) (v10 + 4);
202
            v12 = *(_DWORD *) (v10 + 8);
203
            v10 += 8;
204
            *(_DWORD *) (v9 + 8) = v12;
205
            v9 += 8;
206
        }
207
        while (v11);
208
        if (0x1FFED000u << 20)
209
            __breakpoint(89);
210
        if (0x1FFEC000u << 20)
211
            __breakpoint(90);
212
        ((void (*)(void))sub_FFF2F2CC) ();
213
        sub_FFF2F2CC(0x1FFEC000u, 536547328, 0x1000u);
214
        sub_FFF2F2CC(0x1FFEC000 - (unsigned __int16)&sub_FFF2D000,
215
                 0x1FFAD000u >> 16 << 16,
216
                 (unsigned __int16)&sub_FFF2D000);
217
        __mcr(15, 0, 0, 7, 10, 0);
218
        __mcr(15, 0, 0, 7, 10, 4);
219
        *0x1FFAF41C = 0xFFFF;
220
        result = 0x1FFAF414;
221
        while (*0x1FFAF414 & 1) ;
222
        *0x1FFAF414 = 0;
223
    }
224
    __mcr(15, 0, 0, 7, 14, 0);
225
    __mcr(15, 0, 0, 7, 10, 5);
226
    __mcr(15, 0, 0, 7, 5, 0);
227
    __mcr(15, 0, 0, 7, 5, 6);
228
    __mcr(15, 0, 0, 7, 10, 4);
229
    __mcr(15, 0, 0, 7, 5, 4);
230
    return result;
231
}