Skip to content

Commit 7105908

Browse files
committed
Use templates to generate specialized versions of ppc_effective_to_physical
Helps to avoid some branching when running. Takes the benchmark from ~422 MiB/s to ~433 MiB/s on my machine. Helps a bit less during 10.2 startup (about a 3% improvement) because most accesses on the complex addressing mode code path.
1 parent 2e91c3f commit 7105908

3 files changed

Lines changed: 52 additions & 50 deletions

File tree

src/cpu/cpu_generic/ppc_mmu.cc

Lines changed: 48 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,11 @@ static int ppc_pte_protection[] = {
6868
0, // r
6969
};
7070

71-
inline int FASTCALL ppc_effective_to_physical(uint32 addr, int flags, uint32 &result)
71+
template <int flags>
72+
inline int FASTCALL ppc_effective_to_physical(uint32 addr, uint32 &result)
7273
{
73-
if (flags & PPC_MMU_CODE) {
74-
if (!(gCPU.msr & MSR_IR)) {
74+
if constexpr (flags & PPC_MMU_CODE) {
75+
if (!(gCPU.msr & MSR_IR)) { [[likely]]
7576
result = addr;
7677
return PPC_MMU_OK;
7778
}
@@ -151,7 +152,7 @@ inline int FASTCALL ppc_effective_to_physical(uint32 addr, int flags, uint32 &re
151152
// page address translation
152153
if ((flags & PPC_MMU_CODE) && (sr & SR_N)) {
153154
// segment isnt executable
154-
if (!(flags & PPC_MMU_NO_EXC)) {
155+
if constexpr (!(flags & PPC_MMU_NO_EXC)) {
155156
ppc_exception(PPC_EXC_ISI, PPC_EXC_SRR1_GUARD);
156157
return PPC_MMU_EXC;
157158
}
@@ -173,12 +174,12 @@ inline int FASTCALL ppc_effective_to_physical(uint32 addr, int flags, uint32 &re
173174
key = (sr & SR_Ks) ? 4 : 0;
174175
}
175176

176-
uint32 pte_protection_offset = ((flags&PPC_MMU_WRITE) ? 8:0) + key;
177+
uint32 pte_protection_offset = (flags&PPC_MMU_WRITE ? 8:0) + key;
177178

178179
for (int i=0; i<8; i++) {
179180
uint32 pte;
180181
if (ppc_read_physical_word(pteg_addr, pte)) {
181-
if (!(flags & PPC_MMU_NO_EXC)) {
182+
if constexpr (!(flags & PPC_MMU_NO_EXC)) {
182183
PPC_MMU_ERR("read physical in address translate failed\n");
183184
return PPC_MMU_EXC;
184185
}
@@ -188,21 +189,21 @@ inline int FASTCALL ppc_effective_to_physical(uint32 addr, int flags, uint32 &re
188189
if (VSID == PTE1_VSID(pte) && (api == PTE1_API(pte))) {
189190
// page found
190191
if (ppc_read_physical_word(pteg_addr+4, pte)) {
191-
if (!(flags & PPC_MMU_NO_EXC)) {
192+
if constexpr (!(flags & PPC_MMU_NO_EXC)) {
192193
PPC_MMU_ERR("read physical in address translate failed\n");
193194
return PPC_MMU_EXC;
194195
}
195196
return PPC_MMU_FATAL;
196197
}
197198
// check accessmode .346
198199
if (!ppc_pte_protection[pte_protection_offset + PTE2_PP(pte)]) {
199-
if (!(flags & PPC_MMU_NO_EXC)) {
200-
if (flags & PPC_MMU_CODE) {
200+
if constexpr (!(flags & PPC_MMU_NO_EXC)) {
201+
if constexpr (flags & PPC_MMU_CODE) {
201202
PPC_MMU_WARN("correct impl? code + read protection\n");
202203
ppc_exception(PPC_EXC_ISI, PPC_EXC_SRR1_PROT, addr);
203204
return PPC_MMU_EXC;
204205
} else {
205-
if (flags & PPC_MMU_WRITE) {
206+
if constexpr (flags & PPC_MMU_WRITE) {
206207
ppc_exception(PPC_EXC_DSI, PPC_EXC_DSISR_PROT | PPC_EXC_DSISR_STORE, addr);
207208
} else {
208209
ppc_exception(PPC_EXC_DSI, PPC_EXC_DSISR_PROT, addr);
@@ -223,7 +224,7 @@ inline int FASTCALL ppc_effective_to_physical(uint32 addr, int flags, uint32 &re
223224
// ht_printf("TLB: STORE %d: %08x -> %08x\n", gCPU.tlb_last, addr, pap);
224225
#endif
225226
// update access bits
226-
if (flags & PPC_MMU_WRITE) {
227+
if constexpr (flags & PPC_MMU_WRITE) {
227228
pte |= PTE2_C | PTE2_R;
228229
} else {
229230
pte |= PTE2_R;
@@ -241,7 +242,7 @@ inline int FASTCALL ppc_effective_to_physical(uint32 addr, int flags, uint32 &re
241242
for (int i=0; i<8; i++) {
242243
uint32 pte;
243244
if (ppc_read_physical_word(pteg_addr, pte)) {
244-
if (!(flags & PPC_MMU_NO_EXC)) {
245+
if constexpr (!(flags & PPC_MMU_NO_EXC)) {
245246
PPC_MMU_ERR("read physical in address translate failed\n");
246247
return PPC_MMU_EXC;
247248
}
@@ -251,7 +252,7 @@ inline int FASTCALL ppc_effective_to_physical(uint32 addr, int flags, uint32 &re
251252
if (VSID == PTE1_VSID(pte) && (api == PTE1_API(pte))) {
252253
// page found
253254
if (ppc_read_physical_word(pteg_addr+4, pte)) {
254-
if (!(flags & PPC_MMU_NO_EXC)) {
255+
if constexpr (!(flags & PPC_MMU_NO_EXC)) {
255256
PPC_MMU_ERR("read physical in address translate failed\n");
256257
return PPC_MMU_EXC;
257258
}
@@ -264,14 +265,14 @@ inline int FASTCALL ppc_effective_to_physical(uint32 addr, int flags, uint32 &re
264265
} else {
265266
key = (sr & SR_Ks) ? 4 : 0;
266267
}
267-
if (!ppc_pte_protection[((flags&PPC_MMU_WRITE)?8:0) + key + PTE2_PP(pte)]) {
268-
if (!(flags & PPC_MMU_NO_EXC)) {
269-
if (flags & PPC_MMU_CODE) {
268+
if (!ppc_pte_protection[(flags&PPC_MMU_WRITE?8:0) + key + PTE2_PP(pte)]) {
269+
if constexpr (!(flags & PPC_MMU_NO_EXC)) {
270+
if constexpr (flags & PPC_MMU_CODE) {
270271
PPC_MMU_WARN("correct impl? code + read protection\n");
271272
ppc_exception(PPC_EXC_ISI, PPC_EXC_SRR1_PROT, addr);
272273
return PPC_MMU_EXC;
273274
} else {
274-
if (flags & PPC_MMU_WRITE) {
275+
if constexpr (flags & PPC_MMU_WRITE) {
275276
ppc_exception(PPC_EXC_DSI, PPC_EXC_DSISR_PROT | PPC_EXC_DSISR_STORE, addr);
276277
} else {
277278
ppc_exception(PPC_EXC_DSI, PPC_EXC_DSISR_PROT, addr);
@@ -285,7 +286,7 @@ inline int FASTCALL ppc_effective_to_physical(uint32 addr, int flags, uint32 &re
285286
result = PTE2_RPN(pte) | offset;
286287

287288
// update access bits
288-
if (flags & PPC_MMU_WRITE) {
289+
if constexpr (flags & PPC_MMU_WRITE) {
289290
pte |= PTE2_C | PTE2_R;
290291
} else {
291292
pte |= PTE2_R;
@@ -300,11 +301,11 @@ inline int FASTCALL ppc_effective_to_physical(uint32 addr, int flags, uint32 &re
300301
}
301302
}
302303
// page fault
303-
if (!(flags & PPC_MMU_NO_EXC)) {
304-
if (flags & PPC_MMU_CODE) {
304+
if constexpr (!(flags & PPC_MMU_NO_EXC)) {
305+
if constexpr (flags & PPC_MMU_CODE) {
305306
ppc_exception(PPC_EXC_ISI, PPC_EXC_SRR1_PAGE);
306307
} else {
307-
if (flags & PPC_MMU_WRITE) {
308+
if constexpr (flags & PPC_MMU_WRITE) {
308309
ppc_exception(PPC_EXC_DSI, PPC_EXC_DSISR_PAGE | PPC_EXC_DSISR_STORE, addr);
309310
} else {
310311
ppc_exception(PPC_EXC_DSI, PPC_EXC_DSISR_PAGE, addr);
@@ -417,7 +418,7 @@ int FASTCALL ppc_direct_effective_memory_handle(uint32 addr, byte *&ptr)
417418
{
418419
uint32 ea;
419420
int r;
420-
if (!((r = ppc_effective_to_physical(addr, PPC_MMU_READ, ea)))) {
421+
if (!((r = ppc_effective_to_physical<PPC_MMU_READ>(addr, ea)))) {
421422
return ppc_direct_physical_memory_handle(ea, ptr);
422423
}
423424
return r;
@@ -427,7 +428,7 @@ int FASTCALL ppc_direct_effective_memory_handle_code(uint32 addr, byte *&ptr)
427428
{
428429
uint32 ea;
429430
int r;
430-
if (!((r = ppc_effective_to_physical(addr, PPC_MMU_READ | PPC_MMU_CODE, ea)))) {
431+
if (!((r = ppc_effective_to_physical<PPC_MMU_READ | PPC_MMU_CODE>(addr, ea)))) {
431432
return ppc_direct_physical_memory_handle(ea, ptr);
432433
}
433434
return r;
@@ -502,7 +503,7 @@ inline int FASTCALL ppc_read_effective_code(uint32 addr, uint32 &result)
502503
}
503504
uint32 p;
504505
int r;
505-
if (!((r=ppc_effective_to_physical(addr, PPC_MMU_READ | PPC_MMU_CODE, p)))) {
506+
if (!((r=ppc_effective_to_physical<PPC_MMU_READ | PPC_MMU_CODE>(addr, p)))) {
506507
return ppc_read_physical_word(p, result);
507508
}
508509
return r;
@@ -515,7 +516,7 @@ inline int FASTCALL ppc_read_effective_qword(uint32 addr, Vector_t &result)
515516

516517
addr &= ~0x0f;
517518

518-
if (!(r = ppc_effective_to_physical(addr, PPC_MMU_READ, p))) {
519+
if (!(r = ppc_effective_to_physical<PPC_MMU_READ>(addr, p))) {
519520
return ppc_read_physical_qword(p, result);
520521
}
521522

@@ -526,14 +527,14 @@ inline int FASTCALL ppc_read_effective_dword(uint32 addr, uint64 &result)
526527
{
527528
uint32 p;
528529
int r;
529-
if (!(r = ppc_effective_to_physical(addr, PPC_MMU_READ, p))) {
530+
if (!(r = ppc_effective_to_physical<PPC_MMU_READ>(addr, p))) {
530531
if (EA_Offset(addr) > 4088) {
531532
// read overlaps two pages.. tricky
532533
byte *r1, *r2;
533534
byte b[14];
534-
ppc_effective_to_physical((addr & ~0xfff)+4089, PPC_MMU_READ, p);
535+
ppc_effective_to_physical<PPC_MMU_READ>((addr & ~0xfff)+4089, p);
535536
if ((r = ppc_direct_physical_memory_handle(p, r1))) return r;
536-
if ((r = ppc_effective_to_physical((addr & ~0xfff)+4096, PPC_MMU_READ, p))) return r;
537+
if ((r = ppc_effective_to_physical<PPC_MMU_READ>((addr & ~0xfff)+4096, p))) return r;
537538
if ((r = ppc_direct_physical_memory_handle(p, r2))) return r;
538539
memmove(&b[0], r1, 7);
539540
memmove(&b[7], r2, 7);
@@ -551,14 +552,14 @@ inline int FASTCALL ppc_read_effective_word(uint32 addr, uint32 &result)
551552
{
552553
uint32 p;
553554
int r;
554-
if (!(r = ppc_effective_to_physical(addr, PPC_MMU_READ, p))) {
555+
if (!(r = ppc_effective_to_physical<PPC_MMU_READ>(addr, p))) {
555556
if (EA_Offset(addr) > 4092) {
556557
// read overlaps two pages.. tricky
557558
byte *r1, *r2;
558559
byte b[6];
559-
ppc_effective_to_physical((addr & ~0xfff)+4093, PPC_MMU_READ, p);
560+
ppc_effective_to_physical<PPC_MMU_READ>((addr & ~0xfff)+4093, p);
560561
if ((r = ppc_direct_physical_memory_handle(p, r1))) return r;
561-
if ((r = ppc_effective_to_physical((addr & ~0xfff)+4096, PPC_MMU_READ, p))) return r;
562+
if ((r = ppc_effective_to_physical<PPC_MMU_READ>((addr & ~0xfff)+4096, p))) return r;
562563
if ((r = ppc_direct_physical_memory_handle(p, r2))) return r;
563564
memmove(&b[0], r1, 3);
564565
memmove(&b[3], r2, 3);
@@ -576,13 +577,13 @@ inline int FASTCALL ppc_read_effective_half(uint32 addr, uint16 &result)
576577
{
577578
uint32 p;
578579
int r;
579-
if (!((r = ppc_effective_to_physical(addr, PPC_MMU_READ, p)))) {
580+
if (!((r = ppc_effective_to_physical<PPC_MMU_READ>(addr, p)))) {
580581
if (EA_Offset(addr) > 4094) {
581582
// read overlaps two pages.. tricky
582583
byte b1, b2;
583-
ppc_effective_to_physical((addr & ~0xfff)+4095, PPC_MMU_READ, p);
584+
ppc_effective_to_physical<PPC_MMU_READ>((addr & ~0xfff)+4095, p);
584585
if ((r = ppc_read_physical_byte(p, b1))) return r;
585-
if ((r = ppc_effective_to_physical((addr & ~0xfff)+4096, PPC_MMU_READ, p))) return r;
586+
if ((r = ppc_effective_to_physical<PPC_MMU_READ>((addr & ~0xfff)+4096, p))) return r;
586587
if ((r = ppc_read_physical_byte(p, b2))) return r;
587588
result = (b1<<8)|b2;
588589
return PPC_MMU_OK;
@@ -597,7 +598,7 @@ inline int FASTCALL ppc_read_effective_byte(uint32 addr, uint8 &result)
597598
{
598599
uint32 p;
599600
int r;
600-
if (!((r = ppc_effective_to_physical(addr, PPC_MMU_READ, p)))) {
601+
if (!((r = ppc_effective_to_physical<PPC_MMU_READ>(addr, p)))) {
601602
return ppc_read_physical_byte(p, result);
602603
}
603604
return r;
@@ -669,7 +670,7 @@ inline int FASTCALL ppc_write_effective_qword(uint32 addr, Vector_t data)
669670

670671
addr &= ~0x0f;
671672

672-
if (!((r=ppc_effective_to_physical(addr, PPC_MMU_WRITE, p)))) {
673+
if (!((r=ppc_effective_to_physical<PPC_MMU_WRITE>(addr, p)))) {
673674
return ppc_write_physical_qword(p, data);
674675
}
675676
return r;
@@ -679,14 +680,14 @@ inline int FASTCALL ppc_write_effective_dword(uint32 addr, uint64 data)
679680
{
680681
uint32 p;
681682
int r;
682-
if (!((r=ppc_effective_to_physical(addr, PPC_MMU_WRITE, p)))) {
683+
if (!((r=ppc_effective_to_physical<PPC_MMU_WRITE>(addr, p)))) {
683684
if (EA_Offset(addr) > 4088) {
684685
// write overlaps two pages.. tricky
685686
byte *r1, *r2;
686687
byte b[14];
687-
ppc_effective_to_physical((addr & ~0xfff)+4089, PPC_MMU_WRITE, p);
688+
ppc_effective_to_physical<PPC_MMU_WRITE>((addr & ~0xfff)+4089, p);
688689
if ((r = ppc_direct_physical_memory_handle(p, r1))) return r;
689-
if ((r = ppc_effective_to_physical((addr & ~0xfff)+4096, PPC_MMU_WRITE, p))) return r;
690+
if ((r = ppc_effective_to_physical<PPC_MMU_WRITE>((addr & ~0xfff)+4096, p))) return r;
690691
if ((r = ppc_direct_physical_memory_handle(p, r2))) return r;
691692
data = ppc_dword_to_BE(data);
692693
memmove(&b[0], r1, 7);
@@ -706,14 +707,14 @@ inline int FASTCALL ppc_write_effective_word(uint32 addr, uint32 data)
706707
{
707708
uint32 p;
708709
int r;
709-
if (!((r=ppc_effective_to_physical(addr, PPC_MMU_WRITE, p)))) {
710+
if (!((r=ppc_effective_to_physical<PPC_MMU_WRITE>(addr, p)))) {
710711
if (EA_Offset(addr) > 4092) {
711712
// write overlaps two pages.. tricky
712713
byte *r1, *r2;
713714
byte b[6];
714-
ppc_effective_to_physical((addr & ~0xfff)+4093, PPC_MMU_WRITE, p);
715+
ppc_effective_to_physical<PPC_MMU_WRITE>((addr & ~0xfff)+4093, p);
715716
if ((r = ppc_direct_physical_memory_handle(p, r1))) return r;
716-
if ((r = ppc_effective_to_physical((addr & ~0xfff)+4096, PPC_MMU_WRITE, p))) return r;
717+
if ((r = ppc_effective_to_physical<PPC_MMU_WRITE>((addr & ~0xfff)+4096, p))) return r;
717718
if ((r = ppc_direct_physical_memory_handle(p, r2))) return r;
718719
data = ppc_word_to_BE(data);
719720
memmove(&b[0], r1, 3);
@@ -733,12 +734,12 @@ inline int FASTCALL ppc_write_effective_half(uint32 addr, uint16 data)
733734
{
734735
uint32 p;
735736
int r;
736-
if (!((r=ppc_effective_to_physical(addr, PPC_MMU_WRITE, p)))) {
737+
if (!((r=ppc_effective_to_physical<PPC_MMU_WRITE>(addr, p)))) {
737738
if (EA_Offset(addr) > 4094) {
738739
// write overlaps two pages.. tricky
739-
ppc_effective_to_physical((addr & ~0xfff)+4095, PPC_MMU_WRITE, p);
740+
ppc_effective_to_physical<PPC_MMU_WRITE>((addr & ~0xfff)+4095, p);
740741
if ((r = ppc_write_physical_byte(p, data>>8))) return r;
741-
if ((r = ppc_effective_to_physical((addr & ~0xfff)+4096, PPC_MMU_WRITE, p))) return r;
742+
if ((r = ppc_effective_to_physical<PPC_MMU_WRITE>((addr & ~0xfff)+4096, p))) return r;
742743
if ((r = ppc_write_physical_byte(p, data))) return r;
743744
return PPC_MMU_OK;
744745
} else {
@@ -752,7 +753,7 @@ inline int FASTCALL ppc_write_effective_byte(uint32 addr, uint8 data)
752753
{
753754
uint32 p;
754755
int r;
755-
if (!((r=ppc_effective_to_physical(addr, PPC_MMU_WRITE, p)))) {
756+
if (!((r=ppc_effective_to_physical<PPC_MMU_WRITE>(addr, p)))) {
756757
return ppc_write_physical_byte(p, data);
757758
}
758759
return r;
@@ -821,7 +822,7 @@ bool ppc_prom_set_sdr1(uint32 newval, bool quiesce)
821822

822823
bool ppc_prom_effective_to_physical(uint32 &result, uint32 ea)
823824
{
824-
return ppc_effective_to_physical(ea, PPC_MMU_READ|PPC_MMU_SV|PPC_MMU_NO_EXC, result) == PPC_MMU_OK;
825+
return ppc_effective_to_physical<PPC_MMU_READ|PPC_MMU_SV|PPC_MMU_NO_EXC>(ea, result) == PPC_MMU_OK;
825826
}
826827

827828
bool ppc_prom_page_create(uint32 ea, uint32 pa)

src/cpu/cpu_generic/ppc_mmu.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ extern uint32 gMemorySize;
3737
#define PPC_MMU_EXC 1
3838
#define PPC_MMU_FATAL 2
3939

40-
int FASTCALL ppc_effective_to_physical(uint32 addr, int flags, uint32 &result);
40+
template <int flags>
41+
int FASTCALL ppc_effective_to_physical(uint32 addr, uint32 &result);
4142
bool FASTCALL ppc_mmu_set_sdr1(uint32 newval, bool quiesce);
4243
void ppc_mmu_tlb_invalidate();
4344

src/ppc_bench.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ int ppc_bench() {
4848
uint32 instr_code_be = ppc_word_to_BE(instr_code);
4949
uint32 instr_addr = i * 4;
5050
uint32 instr_physical_addr;
51-
int r = ppc_effective_to_physical(instr_addr, PPC_MMU_WRITE | PPC_MMU_CODE, instr_physical_addr);
51+
int r = ppc_effective_to_physical<PPC_MMU_WRITE>(instr_addr, instr_physical_addr);
5252
if (r != PPC_MMU_OK) {
5353
ht_printf("MMU error when mapping instruction address: %d\n", r);
5454
return 1;
@@ -82,7 +82,7 @@ int ppc_bench() {
8282

8383
uint32 addr = 0x1000+i;
8484
uint32 physical_addr;
85-
int r = ppc_effective_to_physical(addr, PPC_MMU_WRITE, physical_addr);
85+
int r = ppc_effective_to_physical<PPC_MMU_WRITE>(addr, physical_addr);
8686
if (r != PPC_MMU_OK) {
8787
ht_printf("MMU error when mapping data address: %d\n", r);
8888
return 1;

0 commit comments

Comments
 (0)