gpulib: Add proper support for big-endian
authorPaul Cercueil <paul@crapouillou.net>
Fri, 13 Sep 2019 21:13:43 +0000 (23:13 +0200)
committerAsh Logan <ash@heyquark.com>
Mon, 6 Jun 2022 13:05:04 +0000 (23:05 +1000)
Update the gpulib code to work properly on big-endian architectures.

Signed-off-by: Paul Cercueil <paul@crapouillou.net>
plugins/gpulib/gpu.c
plugins/gpulib/gpu.h

index 03e341d..bde6da7 100644 (file)
@@ -464,12 +464,12 @@ static noinline int do_cmd_list_skip(uint32_t *data, int count, int *last_cmd)
 
   while (pos < count && skip) {
     uint32_t *list = data + pos;
-    cmd = list[0] >> 24;
+    cmd = LE32TOH(list[0]) >> 24;
     len = 1 + cmd_lengths[cmd];
 
     switch (cmd) {
       case 0x02:
-        if ((int)(list[2] & 0x3ff) > gpu.screen.w || (int)((list[2] >> 16) & 0x1ff) > gpu.screen.h)
+        if ((LE32TOH(list[2]) & 0x3ff) > gpu.screen.w || ((LE32TOH(list[2]) >> 16) & 0x1ff) > gpu.screen.h)
           // clearing something large, don't skip
           do_cmd_list(list, 3, &dummy);
         else
@@ -480,12 +480,12 @@ static noinline int do_cmd_list_skip(uint32_t *data, int count, int *last_cmd)
       case 0x34 ... 0x37:
       case 0x3c ... 0x3f:
         gpu.ex_regs[1] &= ~0x1ff;
-        gpu.ex_regs[1] |= list[4 + ((cmd >> 4) & 1)] & 0x1ff;
+        gpu.ex_regs[1] |= LE32TOH(list[4 + ((cmd >> 4) & 1)]) & 0x1ff;
         break;
       case 0x48 ... 0x4F:
         for (v = 3; pos + v < count; v++)
         {
-          if ((list[v] & 0xf000f000) == 0x50005000)
+          if ((list[v] & HTOLE32(0xf000f000)) == HTOLE32(0x50005000))
             break;
         }
         len += v - 3;
@@ -493,16 +493,16 @@ static noinline int do_cmd_list_skip(uint32_t *data, int count, int *last_cmd)
       case 0x58 ... 0x5F:
         for (v = 4; pos + v < count; v += 2)
         {
-          if ((list[v] & 0xf000f000) == 0x50005000)
+          if ((list[v] & HTOLE32(0xf000f000)) == HTOLE32(0x50005000))
             break;
         }
         len += v - 4;
         break;
       default:
         if (cmd == 0xe3)
-          skip = decide_frameskip_allow(list[0]);
+          skip = decide_frameskip_allow(LE32TOH(list[0]));
         if ((cmd & 0xf8) == 0xe0)
-          gpu.ex_regs[cmd & 7] = list[0];
+          gpu.ex_regs[cmd & 7] = LE32TOH(list[0]);
         break;
     }
 
@@ -537,7 +537,7 @@ static noinline int do_cmd_buffer(uint32_t *data, int count)
         break;
     }
 
-    cmd = data[pos] >> 24;
+    cmd = LE32TOH(data[pos]) >> 24;
     if (0xa0 <= cmd && cmd <= 0xdf) {
       if (unlikely((pos+2) >= count)) {
         // incomplete vram write/read cmd, can't consume yet
@@ -546,13 +546,13 @@ static noinline int do_cmd_buffer(uint32_t *data, int count)
       }
 
       // consume vram write/read cmd
-      start_vram_transfer(data[pos + 1], data[pos + 2], (cmd & 0xe0) == 0xc0);
+      start_vram_transfer(LE32TOH(data[pos + 1]), LE32TOH(data[pos + 2]), (cmd & 0xe0) == 0xc0);
       pos += 3;
       continue;
     }
 
     // 0xex cmds might affect frameskip.allow, so pass to do_cmd_list_skip
-    if (gpu.frameskip.active && (gpu.frameskip.allow || ((data[pos] >> 24) & 0xf0) == 0xe0))
+    if (gpu.frameskip.active && (gpu.frameskip.allow || ((LE32TOH(data[pos]) >> 24) & 0xf0) == 0xe0))
       pos += do_cmd_list_skip(data + pos, count - pos, &cmd);
     else {
       pos += do_cmd_list(data + pos, count - pos, &cmd);
@@ -601,7 +601,7 @@ void GPUwriteDataMem(uint32_t *mem, int count)
 void GPUwriteData(uint32_t data)
 {
   log_io("gpu_write %08x\n", data);
-  gpu.cmd_buffer[gpu.cmd_len++] = data;
+  gpu.cmd_buffer[gpu.cmd_len++] = HTOLE32(data);
   if (gpu.cmd_len >= CMD_BUFFER_LEN)
     flush_cmd_buffer();
 }
@@ -622,8 +622,8 @@ long GPUdmaChain(uint32_t *rambase, uint32_t start_addr)
   for (count = 0; (addr & 0x800000) == 0; count++)
   {
     list = rambase + (addr & 0x1fffff) / 4;
-    len = list[0] >> 24;
-    addr = list[0] & 0xffffff;
+    len = LE32TOH(list[0]) >> 24;
+    addr = LE32TOH(list[0]) & 0xffffff;
     preload(rambase + (addr & 0x1fffff) / 4);
 
     cpu_cycles += 10;
@@ -648,7 +648,7 @@ long GPUdmaChain(uint32_t *rambase, uint32_t start_addr)
       // loop detection marker
       // (bit23 set causes DMA error on real machine, so
       //  unlikely to be ever set by the game)
-      list[0] |= 0x800000;
+      list[0] |= HTOLE32(0x800000);
     }
   }
 
@@ -658,8 +658,8 @@ long GPUdmaChain(uint32_t *rambase, uint32_t start_addr)
     addr = ld_addr & 0x1fffff;
     while (count-- > 0) {
       list = rambase + addr / 4;
-      addr = list[0] & 0x1fffff;
-      list[0] &= ~0x800000;
+      addr = LE32TOH(list[0]) & 0x1fffff;
+      list[0] &= HTOLE32(~0x800000);
     }
   }
 
index 9f42714..848c6dc 100644 (file)
@@ -19,6 +19,18 @@ extern "C" {
 
 #define CMD_BUFFER_LEN          1024
 
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define HTOLE32(x) __builtin_bswap32(x)
+#define HTOLE16(x) __builtin_bswap16(x)
+#define LE32TOH(x) __builtin_bswap32(x)
+#define LE16TOH(x) __builtin_bswap16(x)
+#else
+#define HTOLE32(x) (x)
+#define HTOLE16(x) (x)
+#define LE32TOH(x) (x)
+#define LE16TOH(x) (x)
+#endif
+
 #define BIT(x) (1 << (x))
 
 #define PSX_GPU_STATUS_DHEIGHT         BIT(19)