Skip to content

Commit 153bf96

Browse files
QuzarDCQuzarDC
authored andcommitted
maple_enum: Leverage builtins to simplify enum matching.
The use of the byteswap is straightforward. The algorithm for determining which `function_data` element contains the data relevant to the function at hand used to go bit by bit counting how many bits are above the function bit, as the elements of `function_data` map from MSB down to up to 3 functions. Instead of looping over the bits, build a mask to mask out everything but bits that would appear above the desired function bit, then count how many there are left with popcount.
1 parent 358d9c4 commit 153bf96

1 file changed

Lines changed: 18 additions & 20 deletions

File tree

kernel/arch/dreamcast/hardware/maple/maple_enum.c

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88
#include <dc/maple.h>
99
#include <kos/thread.h>
10+
#include <kos/regfield.h>
11+
#include <assert.h>
1012

1113
/* Return the number of connected devices */
1214
int maple_enum_count(void) {
@@ -22,15 +24,15 @@ int maple_enum_count(void) {
2224
}
2325

2426
/* Return a raw device info struct for the given device */
25-
maple_device_t * maple_enum_dev(int p, int u) {
27+
maple_device_t *maple_enum_dev(int p, int u) {
2628
maple_device_t *rv = maple_state.ports[p].units[u];
2729
if(rv && rv->valid)
2830
return rv;
2931
return NULL;
3032
}
3133

3234
/* Return the Nth device of the requested type (where N is zero-indexed) */
33-
maple_device_t * maple_enum_type(int n, uint32_t func) {
35+
maple_device_t *maple_enum_type(int n, uint32_t func) {
3436
int p, u;
3537
maple_device_t *dev;
3638

@@ -51,10 +53,16 @@ maple_device_t * maple_enum_type(int n, uint32_t func) {
5153

5254
/* Return the Nth device that is of the requested type and supports the list of
5355
capabilities given. */
54-
maple_device_t * maple_enum_type_ex(int n, uint32_t func, uint32_t cap) {
56+
maple_device_t *maple_enum_type_ex(int n, uint32_t func, uint32_t cap) {
5557
int p, u, d;
5658
maple_device_t *dev;
57-
uint32_t f, tmp;
59+
uint32_t funcmask;
60+
61+
/* If func is 0, there can be no match (and it's UB for clz below) */
62+
if(!func) return NULL;
63+
64+
/* Create a mask that leaves only the bits above func. */
65+
funcmask = ~GENMASK(31 - __builtin_clz(func), 0);
5866

5967
for(p = 0; p < MAPLE_PORT_COUNT; ++p) {
6068
for(u = 0; u < MAPLE_UNIT_COUNT; ++u) {
@@ -63,28 +71,18 @@ maple_device_t * maple_enum_type_ex(int n, uint32_t func, uint32_t cap) {
6371
/* If the device supports the function code we passed in, check
6472
if it supports the capabilities that the user requested. */
6573
if(dev != NULL && (dev->info.functions & func)) {
66-
f = dev->info.functions;
67-
d = 0;
68-
tmp = func;
6974

7075
/* Figure out which function data we want to look at. Function
7176
data entries are arranged by the function code, most
72-
significant bit first. This is really not pretty, and is
73-
rather inefficient, but its the best I could think of off the
74-
top of my head (i.e, replace me later). */
75-
while(tmp != 0x80000000) {
76-
if(f & 0x80000000) {
77-
++d;
78-
}
79-
80-
f <<= 1;
81-
tmp <<= 1;
82-
}
77+
significant bit first. So we count the bits above func. */
78+
d = __builtin_popcount(dev->info.functions & funcmask);
79+
80+
/* Ensure that the result is in-bounds */
81+
assert((d >= 0) && (d < 3));
8382

8483
/* Check if the function data for the function type checks out
8584
with what it should be. */
86-
cap = ((cap >> 24) & 0xFF) | ((cap >> 8) & 0xFF00) |
87-
((cap & 0xFF00) << 8) | ((cap & 0xFF) << 24);
85+
cap = __builtin_bswap32(cap);
8886

8987
if((dev->info.function_data[d] & cap) == cap) {
9088
if(!n)

0 commit comments

Comments
 (0)