From 3bc15e631d2ac7e42b50e2ec87e30cceaafdc2e3 Mon Sep 17 00:00:00 2001 From: Francisco Javier Trujillo Mata Date: Sun, 3 Feb 2019 12:57:15 +0100 Subject: [PATCH] Implement the Palette for PS2 --- Makefile.libretro | 7 +- pico/mode4.c | 12 +- .../include/libretro_gskit_ps2.h | 68 + platform/libretro/libretro.c | 156 +- platform/ps2/Draw_mips_r5900.s | 1799 +++++++++++++++++ platform/ps2/Memory_mips_r5900.s | 847 ++++++++ platform/ps2/SMS_Utils.s | 202 ++ platform/ps2/asm.h | 3 + platform/ps2/asm.s | 129 ++ 9 files changed, 3208 insertions(+), 15 deletions(-) create mode 100644 platform/libretro/libretro-common/include/libretro_gskit_ps2.h create mode 100644 platform/ps2/Draw_mips_r5900.s create mode 100644 platform/ps2/Memory_mips_r5900.s create mode 100644 platform/ps2/SMS_Utils.s create mode 100644 platform/ps2/asm.h create mode 100644 platform/ps2/asm.s diff --git a/Makefile.libretro b/Makefile.libretro index efb81ebf..e1ec1d99 100644 --- a/Makefile.libretro +++ b/Makefile.libretro @@ -259,7 +259,9 @@ else ifeq ($(platform), ps2) TARGET := $(TARGET_NAME)_libretro_$(platform).a CC = ee-gcc$(EXE_EXT) AR = ee-ar$(EXE_EXT) - CFLAGS += -G0 -Wall -DPS2 -DUSE_BGR555 -DUTYPES_DEFINED -DFAMEC_NO_GOTOS -fsingle-precision-constant + CFLAGS += -G0 -Wall -DPS2 -DUSE_BGR555 -DUTYPES_DEFINED -DFAMEC_NO_GOTOS -DRENDER_GSKIT_PS2 -fsingle-precision-constant + CFLAGS += -Dmemcpy=mips_memcpy -Dmemset=mips_memset + # CFLAGS += -D_ASM_MISC_C_AMIPS -D_ASM_DRAW_C_AMIPS -D_ASM_MEMORY_C_AMIPS CFLAGS += -I$(PS2SDK)/ports/include -I$(PS2DEV)/gsKit/include -I$(PS2SDK)/ee/include -I$(PS2SDK)/common/include -Iplatform/ps2 STATIC_LINKING = 1 NO_MMAP = 1 @@ -277,6 +279,9 @@ else ifeq ($(platform), ps2) use_drz80 = 0 use_cz80 = 1 + OBJS += platform/ps2/asm.o platform/ps2/SMS_Utils.o + # OBJS += platform/ps2/Draw_mips_r5900.o platform/ps2/Memory_mips_r5900.o pico/misc_amips.o + # CTR (3DS) else ifeq ($(platform), ctr) TARGET := $(TARGET_NAME)_libretro_$(platform).a diff --git a/pico/mode4.c b/pico/mode4.c index b8f802e6..5293cc9f 100644 --- a/pico/mode4.c +++ b/pico/mode4.c @@ -284,10 +284,16 @@ static void FinalizeLine8bitM4(int line) { unsigned char *pd = Pico.est.DrawLineDest; - if (!(PicoIn.opt & POPT_DIS_32C_BORDER)) +#if defined(RENDER_GSKIT_PS2) + memcpy(pd, Pico.est.HighCol, 328); +#else + if (!(PicoIn.opt & POPT_DIS_32C_BORDER)) { pd += 32; - - memcpy(pd, Pico.est.HighCol + 8, 256); + memcpy(pd, Pico.est.HighCol + 8, 256); + } else { + memcpy(pd, Pico.est.HighCol + 8, 320); + } +#endif } void PicoDrawSetOutputMode4(pdso_t which) diff --git a/platform/libretro/libretro-common/include/libretro_gskit_ps2.h b/platform/libretro/libretro-common/include/libretro_gskit_ps2.h new file mode 100644 index 00000000..f7b61dc2 --- /dev/null +++ b/platform/libretro/libretro-common/include/libretro_gskit_ps2.h @@ -0,0 +1,68 @@ +/* Copyright (C) 2010-2018 The RetroArch team + * + * --------------------------------------------------------------------------------------------- + * The following license statement only applies to this libretro API header (libretro_d3d.h) + * --------------------------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, + * to any person obtaining a copy of this software and associated documentation files (the + * "Software"), + * to deal in the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef LIBRETRO_GSKIT_PS2_H_ +#define LIBRETRO_GSKIT_PS2_H_ + +#include "libretro.h" + +#if defined(PS2) + +#include + +#define RETRO_HW_RENDER_INTERFACE_GSKIT_PS2_VERSION 1 + +struct retro_hw_ps2_insets +{ + float top; + float left; + float bottom; + float right; +}; + +#define empty_ps2_insets (struct retro_hw_ps2_insets){0.f, 0.f, 0.f, 0.f} + +struct retro_hw_render_interface_gskit_ps2 +{ + /* Must be set to RETRO_HW_RENDER_INTERFACE_GSKIT_PS2. */ + enum retro_hw_render_interface_type interface_type; + /* Must be set to RETRO_HW_RENDER_INTERFACE_GSKIT_PS2_VERSION. */ + unsigned interface_version; + + /* Opaque handle to the GSKit_PS2 backend in the frontend + * which must be passed along to all function pointers + * in this interface. + */ + GSTEXTURE *coreTexture; + bool clearTexture; + bool updatedPalette; + struct retro_hw_ps2_insets padding; +}; +typedef struct retro_hw_render_interface_gskit_ps2 RETRO_HW_RENDER_INTEFACE_GSKIT_PS2; + +#endif + +#endif /* LIBRETRO_GSKIT_PS2_H_ */ diff --git a/platform/libretro/libretro.c b/platform/libretro/libretro.c index 7eb55637..62cbf046 100644 --- a/platform/libretro/libretro.c +++ b/platform/libretro/libretro.c @@ -35,6 +35,11 @@ #include "file_stream_transforms.h" #endif +#if defined(RENDER_GSKIT_PS2) +#include "libretro-common/include/libretro_gskit_ps2.h" +#include "../ps2/asm.h" +#endif + #ifdef _3DS #include "3ds/3ds_utils.h" #define MEMOP_MAP 4 @@ -74,8 +79,14 @@ static retro_input_state_t input_state_cb; static retro_environment_t environ_cb; static retro_audio_sample_batch_t audio_batch_cb; +#if defined(RENDER_GSKIT_PS2) +#define VOUT_MAX_WIDTH 328 +#else #define VOUT_MAX_WIDTH 320 +#define VOUT_32BIT_WIDTH 256 +#endif #define VOUT_MAX_HEIGHT 240 +#define SND_RATE 44100 static const float VOUT_PAR = 0.0; static const float VOUT_4_3 = (224.0f * (4.0f / 3.0f)); @@ -87,7 +98,13 @@ static void *vout_buf; static int vout_width, vout_height, vout_offset; static float user_vout_width = 0.0; -static short ALIGNED(4) sndBuffer[2*44100/50]; +#if defined(RENDER_GSKIT_PS2) +RETRO_HW_RENDER_INTEFACE_GSKIT_PS2 *ps2 = NULL; +static void *retro_palette; +static struct retro_hw_ps2_insets padding; +#endif + +static short ALIGNED(4) sndBuffer[2*SND_RATE/50]; static void snd_write(int len); @@ -492,14 +509,33 @@ void emu_video_mode_change(int start_line, int line_count, int is_32cols) { struct retro_system_av_info av_info; - memset(vout_buf, 0, 320 * 240 * 2); - vout_width = is_32cols ? 256 : 320; +#if defined(RENDER_GSKIT_PS2) + if (is_32cols) { + padding = (struct retro_hw_ps2_insets){start_line, 16.0f, VOUT_MAX_HEIGHT - line_count - start_line, 64.0f}; + } else { + padding = (struct retro_hw_ps2_insets){start_line, 16.0f, VOUT_MAX_HEIGHT - line_count - start_line, 0.0f}; + } + + vout_width = VOUT_MAX_WIDTH; + vout_height = VOUT_MAX_HEIGHT; + memset(vout_buf, 0, vout_width * VOUT_MAX_HEIGHT); + memset(retro_palette, 0, gsKit_texture_size_ee(16, 16, GS_PSM_CT16)); + PicoDrawSetOutBuf(vout_buf, vout_width); + + if (ps2) { + ps2->clearTexture = true; + } +#else + vout_width = is_32cols ? VOUT_32BIT_WIDTH : VOUT_MAX_WIDTH; + memset(vout_buf, 0, VOUT_MAX_WIDTH * VOUT_MAX_HEIGHT * 2); PicoDrawSetOutBuf(vout_buf, vout_width * 2); - if (show_overscan == true) line_count += 16; + + if (show_overscan == true) line_count += 16; if (show_overscan == true) start_line -= 8; vout_height = line_count; vout_offset = vout_width * start_line; +#endif // Update the geometry retro_get_system_av_info(&av_info); @@ -593,7 +629,7 @@ void retro_get_system_av_info(struct retro_system_av_info *info) memset(info, 0, sizeof(*info)); info->timing.fps = Pico.m.pal ? 50 : 60; - info->timing.sample_rate = 44100; + info->timing.sample_rate = SND_RATE; info->geometry.base_width = vout_width; info->geometry.base_height = vout_height; info->geometry.max_width = vout_width; @@ -1360,6 +1396,7 @@ void retro_run(void) { bool updated = false; int pad, i; + static void *buff; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) update_variables(); @@ -1375,7 +1412,93 @@ void retro_run(void) PicoPatchApply(); PicoFrame(); - video_cb((short *)vout_buf + vout_offset, +#if defined(RENDER_GSKIT_PS2) + buff = (uint32_t *)RETRO_HW_FRAME_BUFFER_VALID; + + if (!ps2) { + if (!environ_cb(RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE, (void **)&ps2) || !ps2) { + printf("Failed to get HW rendering interface!\n"); + return; + } + + if (ps2->interface_version != RETRO_HW_RENDER_INTERFACE_GSKIT_PS2_VERSION) { + printf("HW render interface mismatch, expected %u, got %u!\n", + RETRO_HW_RENDER_INTERFACE_GSKIT_PS2_VERSION, ps2->interface_version); + return; + } + + ps2->coreTexture->Width = vout_width; + ps2->coreTexture->Height = vout_height; + ps2->coreTexture->PSM = GS_PSM_T8; + ps2->coreTexture->ClutPSM = GS_PSM_CT16; + ps2->coreTexture->Filter = GS_FILTER_LINEAR; + ps2->coreTexture->Clut = retro_palette; + } + + if (Pico.m.dirtyPal) { + int i; + unsigned short int *pal=(void *)ps2->coreTexture->Clut; + + if (PicoIn.AHW & PAHW_SMS) { + // SMS + unsigned int *spal=(void *)PicoMem.cram; + unsigned int *dpal=(void *)pal; + unsigned int t; + + /* cram is always stored as shorts, even though real hardware probably uses bytes */ + for (i = 0x20/2; i > 0; i--, spal++, dpal++) { + t = *spal; + t = ((t & 0x00030003)<< 3) | ((t & 0x000c000c)<<6) | ((t & 0x00300030)<<9); + t |= t >> 2; + t |= (t >> 4) & 0x08610861; + *dpal = t; + } + pal[0xe0] = 0; + + + } else if (PicoIn.AHW & PAHW_32X) { + // MCD+32X + } else if (PicoIn.AHW & PAHW_MCD) { + // MCD + } else { + // MD + if(Pico.video.reg[0xC]&8){ + do_pal_convert_with_shadows(pal, PicoMem.cram); + } else { + do_pal_convert(pal, PicoMem.cram); + if (Pico.est.rendstatus & PDRAW_SONIC_MODE) { + memcpy(&pal[0x80], pal, 0x40*2); + } + } + } + + + //Rotate CLUT. + for (i = 0; i < 256; i++) { + if ((i&0x18) == 8) { + unsigned short int tmp = pal[i]; + pal[i] = pal[i+8]; + pal[i+8] = tmp; + } + } + + Pico.m.dirtyPal = 0; + ps2->updatedPalette = true; + } + + if (PicoIn.AHW & PAHW_SMS) { + ps2->coreTexture->Mem = vout_buf; + } else { + ps2->coreTexture->Mem = Pico.est.Draw2FB; + } + + ps2->padding = padding; + +#else + buff = vout_buf + vout_offset; +#endif + + video_cb((short *)buff, vout_width, vout_height, vout_width * 2); } @@ -1410,20 +1533,29 @@ void retro_init(void) #endif PicoIn.opt |= POPT_EN_DRC; #endif - PicoIn.sndRate = 44100; + PicoIn.sndRate = SND_RATE; PicoIn.autoRgnOrder = 0x184; // US, EU, JP - vout_width = 320; - vout_height = 240; + vout_width = VOUT_MAX_WIDTH; + vout_height = VOUT_MAX_HEIGHT; #ifdef _3DS vout_buf = linearMemAlign(VOUT_MAX_WIDTH * VOUT_MAX_HEIGHT * 2, 0x80); +#elif defined(RENDER_GSKIT_PS2) + vout_buf = memalign(128, VOUT_MAX_WIDTH * VOUT_MAX_HEIGHT); + retro_palette = memalign(128, gsKit_texture_size_ee(16, 16, GS_PSM_CT16)); #else vout_buf = malloc(VOUT_MAX_WIDTH * VOUT_MAX_HEIGHT * 2); #endif PicoInit(); +#if defined(RENDER_GSKIT_PS2) + PicoDrawSetOutFormat(PDF_NONE, 0); + PicoDrawSetOutBuf(vout_buf, vout_width); + PicoDrawSetOutputMode4(PDF_8BIT); +#else PicoDrawSetOutFormat(PDF_RGB555, 0); PicoDrawSetOutBuf(vout_buf, vout_width * 2); +#endif //PicoIn.osdMessage = plat_status_msg_busy_next; PicoIn.mcdTrayOpen = disk_tray_open; @@ -1436,11 +1568,13 @@ void retro_deinit(void) { #ifdef _3DS linearFree(vout_buf); +#elif defined(RENDER_GSKIT_PS2) + free(vout_buf); + free(retro_palette); + ps2 = NULL; #else free(vout_buf); #endif vout_buf = NULL; PicoExit(); } - -// vim:shiftwidth=3:ts=3:expandtab diff --git a/platform/ps2/Draw_mips_r5900.s b/platform/ps2/Draw_mips_r5900.s new file mode 100644 index 00000000..9179801d --- /dev/null +++ b/platform/ps2/Draw_mips_r5900.s @@ -0,0 +1,1799 @@ +# vim:filetype=mips + +# several drawing related functions for MIPS R5900. Based on Draw_amips.s by Notaz. +# (c) Copyright 2007, Grazvydas "notaz" Ignotas +# All Rights Reserved + +.set noreorder # don't reorder any instructions +.set noat # don't use $at. $at is used for substitute macro instructions (and some replacement code). + +.text +.align 4 + +.macro ext dest,src,pos,size + srl \dest, \src, \pos + li $at, ((1 << \size) - 1) + and \dest, $at +.endm + +.macro rotr dest,src,shift + srl $at, \src, \shift + sll \dest, \src, (32-\shift) + or \dest, $at +.endm + + +# Note: Assumes that n is a multiple of 16. +# void blockcpy_or(void *dst, void *src, size_t n, int pat) +.global blockcpy_or +.ent blockcpy_or +blockcpy_or: + #Spread my beauties! Multiply and divide! :D + sll $t0, $a3, 8 + or $a3, $a3, $t0 + pcpyld $a3, $a3 + pcpyh $a3, $a3 + +blockcpy_or_loop: + ld $t0, 8($a1) + ld $t1, 0($a1) + pcpyld $t0, $t0, $t1 +# lq $t0, 0($a1) #This won't work because the data may not be aligned to a 128-bit address (And unless the source code of Picodrive is modified for that purpose, use two dword loads instead). :( + + por $t0, $t0, $a3 + sq $t0, 0($a0) + + addiu $a2, $a2, -16 + addiu $a0, $a0, 16 + bgtz $a2, blockcpy_or_loop + addiu $a1, $a1, 16 + + jr $ra + nop +.end blockcpy_or + +# void amips_clut(unsigned short *dst, unsigned char *src, unsigned short *pal, int count) + +.global amips_clut + +amips_clut: +amips_clut_loop: + lbu $t0, 0($a1) # tried lw here, no improvement noticed + lbu $t1, 1($a1) + lbu $t2, 2($a1) + lbu $t3, 3($a1) + sll $t0, 1 + sll $t1, 1 + sll $t2, 1 + sll $t3, 1 + addu $t0, $a2 + addu $t1, $a2 + addu $t2, $a2 + addu $t3, $a2 + lhu $t0, 0($t0) + lhu $t1, 0($t1) + lhu $t2, 0($t2) + lhu $t3, 0($t3) + sll $t1, $t1, 16 + or $t0, $t0, $t1 + sll $t3, $t3, 16 + or $t2, $t2, $t3 + sw $t0, 0($a0) + sw $t2, 4($a0) + addiu $a0, 8 + addiu $a3, -4 + bnez $a3, amips_clut_loop + addiu $a1, 4 + jr $ra + nop + + +.global amips_clut_6bit + +amips_clut_6bit: +amips_clut_loop6: + lw $t0, 0($a1) + sll $t4, $t0, 1 + andi $t4, $t4, 0x7E + srl $t5, $t0, 7 + andi $t5, $t5, 0x7E + srl $t6, $t0, 15 + andi $t6, $t6, 0x7E + srl $t7, $t0, 23 + andi $t7, $t7, 0x7E + addu $t0, $t4, $a2 + addu $t1, $t5, $a2 + addu $t2, $t6, $a2 + addu $t3, $t7, $a2 + lhu $t0, 0($t0) + lhu $t1, 0($t1) + lhu $t2, 0($t2) + lhu $t3, 0($t3) + sll $t1, $t1, 16 + or $t0, $t0, $t1 + sll $t3, $t3, 16 + or $t2, $t2, $t3 + sw $t0, 0($a0) + sw $t2, 4($a0) + addiu $a0, 8 + addiu $a3, -4 + bnez $a3, amips_clut_loop6 + addiu $a1, 4 + jr $ra + nop + +# $a0 - pd, $a1 - tile word, $a2 - pal +# ext rt, rs, pos, size // Extract size bits from position pos in rs and store in rt + +.macro TilePixelPrep shift dreg offs +.if \shift + ext \dreg, $a1, \shift, 4 +.else + andi \dreg, $a1, 0xf +.endif +.if \offs + sltu $t8, $0, \dreg + li $at, ~(1<<\offs) + and $t9, $t9, $at + andi $at, $t8, 1 + sll $at, $at, \offs + or $t9, $t9, $at +.else + sltu $t9, $0, \dreg +.endif +.endm + +.macro TileStartCode + sll $a1, $a1, 1 + lui $t1, %hi(Pico+0x10000) + addu $a1, $a1, $t1 + lw $a1, %lo(Pico+0x10000)($a1) # Pico.vram + addr + beqz $a1, TileEmpty + rotr $t1, $a1, 4 #Leaving this macro here is fine because TileEmpty doesn't use the result of this operation. + beq $t1, $a1, SingleColor + and $v0, $0 # not empty tile +.endm + +.macro TileEndCode + xori $t8, $t9, 0xff + beqz $t8, tile11111111 # common case + lui $v1, %hi(HighCol) + addiu $v1, %lo(HighCol) + lui $t8, %hi(TileTable) + li $at, 0xFFFFFC03 + and $t8, $t8, $at + andi $at, $t9, 0xFF + sll $at, $at, 2 + or $t8, $t8, $at + lw $t8, %lo(TileTable)($t8) + jr $t8 + addu $a0, $v1 +.endm + + +.global TileNorm + +TileNorm: + TileStartCode + TilePixelPrep 12, $t0, 0 + TilePixelPrep 8, $t1, 1 + TilePixelPrep 4, $t2, 2 + TilePixelPrep 0, $t3, 3 + TilePixelPrep 28, $t4, 4 + TilePixelPrep 24, $t5, 5 + TilePixelPrep 20, $t6, 6 + TilePixelPrep 16, $t7, 7 + TileEndCode + + +.global TileFlip + +TileFlip: + TileStartCode + TilePixelPrep 16, $t0, 0 + TilePixelPrep 20, $t1, 1 + TilePixelPrep 24, $t2, 2 + TilePixelPrep 28, $t3, 3 + TilePixelPrep 0, $t4, 4 + TilePixelPrep 4, $t5, 5 + TilePixelPrep 8, $t6, 6 + TilePixelPrep 12, $t7, 7 + TileEndCode + + +SingleColor: + la $t9, HighCol + andi $t0, $a1, 0xf + or $t0, $t0, $a2 + addu $a0, $t9 + sb $t0, 0($a0) + sb $t0, 1($a0) + sb $t0, 2($a0) + sb $t0, 3($a0) + sb $t0, 4($a0) + sb $t0, 5($a0) + sb $t0, 6($a0) + jr $ra + sb $t0, 7($a0) + +TileEmpty: + jr $ra + or $v0, $0, 1 # empty tile + +tile11111111: + la $v1, HighCol + or $t0, $t0, $a2 + addu $a0, $v1 + sb $t0, 0($a0) +tile11111110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile11111100: + or $t2, $t2, $a2 + sb $t2, 2($a0) +tile11111000: + or $t3, $t3, $a2 + sb $t3, 3($a0) +tile11110000: + or $t4, $t4, $a2 + sb $t4, 4($a0) +tile11100000: + or $t5, $t5, $a2 + sb $t5, 5($a0) +tile11000000: + or $t6, $t6, $a2 + sb $t6, 6($a0) +tile10000000: + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11111101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11111011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile11111010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11111001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11110111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile11110110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile11110100: + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11110101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11110011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile11110010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11110001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11101111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile11101110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile11101100: + or $t2, $t2, $a2 + sb $t2, 2($a0) +tile11101000: + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11101101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11101011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile11101010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11101001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11100111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile11100110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile11100100: + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11100101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11100011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile11100010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11100001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11011111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile11011110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile11011100: + or $t2, $t2, $a2 + sb $t2, 2($a0) +tile11011000: + or $t3, $t3, $a2 + sb $t3, 3($a0) +tile11010000: + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11011101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11011011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile11011010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11011001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11010111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile11010110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile11010100: + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11010101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11010011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile11010010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11010001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11001111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile11001110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile11001100: + or $t2, $t2, $a2 + sb $t2, 2($a0) +tile11001000: + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11001101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11001011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile11001010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11001001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11000111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile11000110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile11000100: + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11000101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11000011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile11000010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile11000001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t6, $t6, $a2 + sb $t6, 6($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10111111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile10111110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile10111100: + or $t2, $t2, $a2 + sb $t2, 2($a0) +tile10111000: + or $t3, $t3, $a2 + sb $t3, 3($a0) +tile10110000: + or $t4, $t4, $a2 + sb $t4, 4($a0) +tile10100000: + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10111101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10111011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile10111010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10111001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10110111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile10110110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile10110100: + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10110101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10110011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile10110010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10110001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10101111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile10101110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile10101100: + or $t2, $t2, $a2 + sb $t2, 2($a0) +tile10101000: + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10101101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10101011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile10101010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10101001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10100111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile10100110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile10100100: + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10100101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10100011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile10100010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10100001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10011111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile10011110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile10011100: + or $t2, $t2, $a2 + sb $t2, 2($a0) +tile10011000: + or $t3, $t3, $a2 + sb $t3, 3($a0) +tile10010000: + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10011101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10011011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile10011010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10011001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10010111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile10010110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile10010100: + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10010101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10010011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile10010010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10010001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10001111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile10001110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile10001100: + or $t2, $t2, $a2 + sb $t2, 2($a0) +tile10001000: + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10001101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10001011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile10001010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10001001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10000111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile10000110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile10000100: + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10000101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10000011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile10000010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile10000001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t7, $t7, $a2 + jr $ra + sb $t7, 7($a0) +tile01111111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile01111110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile01111100: + or $t2, $t2, $a2 + sb $t2, 2($a0) +tile01111000: + or $t3, $t3, $a2 + sb $t3, 3($a0) +tile01110000: + or $t4, $t4, $a2 + sb $t4, 4($a0) +tile01100000: + or $t5, $t5, $a2 + sb $t5, 5($a0) +tile01000000: + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile00000000: +tile01111101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01111011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile01111010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01111001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01110111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile01110110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile01110100: + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01110101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01110011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile01110010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01110001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01101111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile01101110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile01101100: + or $t2, $t2, $a2 + sb $t2, 2($a0) +tile01101000: + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01101101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01101011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile01101010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01101001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01100111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile01100110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile01100100: + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01100101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01100011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile01100010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01100001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t5, $t5, $a2 + sb $t5, 5($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01011111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile01011110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile01011100: + or $t2, $t2, $a2 + sb $t2, 2($a0) +tile01011000: + or $t3, $t3, $a2 + sb $t3, 3($a0) +tile01010000: + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01011101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01011011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile01011010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01011001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01010111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile01010110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile01010100: + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01010101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01010011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile01010010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01010001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01001111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile01001110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile01001100: + or $t2, $t2, $a2 + sb $t2, 2($a0) +tile01001000: + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01001101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01001011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile01001010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01001001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01000111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile01000110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile01000100: + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01000101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01000011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile01000010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile01000001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t6, $t6, $a2 + jr $ra + sb $t6, 6($a0) +tile00111111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile00111110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile00111100: + or $t2, $t2, $a2 + sb $t2, 2($a0) +tile00111000: + or $t3, $t3, $a2 + sb $t3, 3($a0) +tile00110000: + or $t4, $t4, $a2 + sb $t4, 4($a0) +tile00100000: + or $t5, $t5, $a2 + jr $ra + sb $t5, 5($a0) +tile00111101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + jr $ra + sb $t5, 5($a0) +tile00111011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile00111010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + jr $ra + sb $t5, 5($a0) +tile00111001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + jr $ra + sb $t5, 5($a0) +tile00110111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile00110110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile00110100: + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + jr $ra + sb $t5, 5($a0) +tile00110101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + jr $ra + sb $t5, 5($a0) +tile00110011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile00110010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + jr $ra + sb $t5, 5($a0) +tile00110001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t4, $t4, $a2 + sb $t4, 4($a0) + or $t5, $t5, $a2 + jr $ra + sb $t5, 5($a0) +tile00101111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile00101110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile00101100: + or $t2, $t2, $a2 + sb $t2, 2($a0) +tile00101000: + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t5, $t5, $a2 + jr $ra + sb $t5, 5($a0) +tile00101101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t5, $t5, $a2 + jr $ra + sb $t5, 5($a0) +tile00101011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile00101010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t5, $t5, $a2 + jr $ra + sb $t5, 5($a0) +tile00101001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t5, $t5, $a2 + jr $ra + sb $t5, 5($a0) +tile00100111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile00100110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile00100100: + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t5, $t5, $a2 + jr $ra + sb $t5, 5($a0) +tile00100101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t5, $t5, $a2 + jr $ra + sb $t5, 5($a0) +tile00100011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile00100010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t5, $t5, $a2 + jr $ra + sb $t5, 5($a0) +tile00100001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t5, $t5, $a2 + jr $ra + sb $t5, 5($a0) +tile00011111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile00011110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile00011100: + or $t2, $t2, $a2 + sb $t2, 2($a0) +tile00011000: + or $t3, $t3, $a2 + sb $t3, 3($a0) +tile00010000: + or $t4, $t4, $a2 + jr $ra + sb $t4, 4($a0) +tile00011101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t4, $t4, $a2 + jr $ra + sb $t4, 4($a0) +tile00011011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile00011010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t4, $t4, $a2 + jr $ra + sb $t4, 4($a0) +tile00011001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t3, $t3, $a2 + sb $t3, 3($a0) + or $t4, $t4, $a2 + jr $ra + sb $t4, 4($a0) +tile00010111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile00010110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile00010100: + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t4, $t4, $a2 + jr $ra + sb $t4, 4($a0) +tile00010101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t4, $t4, $a2 + jr $ra + sb $t4, 4($a0) +tile00010011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile00010010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t4, $t4, $a2 + jr $ra + sb $t4, 4($a0) +tile00010001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t4, $t4, $a2 + jr $ra + sb $t4, 4($a0) +tile00001111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile00001110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile00001100: + or $t2, $t2, $a2 + sb $t2, 2($a0) +tile00001000: + or $t3, $t3, $a2 + jr $ra + sb $t3, 3($a0) +tile00001101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + sb $t2, 2($a0) + or $t3, $t3, $a2 + jr $ra + sb $t3, 3($a0) +tile00001011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile00001010: + or $t1, $t1, $a2 + sb $t1, 1($a0) + or $t3, $t3, $a2 + jr $ra + sb $t3, 3($a0) +tile00001001: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t3, $t3, $a2 + jr $ra + sb $t3, 3($a0) +tile00000111: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile00000110: + or $t1, $t1, $a2 + sb $t1, 1($a0) +tile00000100: + or $t2, $t2, $a2 + jr $ra + sb $t2, 2($a0) +tile00000101: + or $t0, $t0, $a2 + sb $t0, 0($a0) + or $t2, $t2, $a2 + jr $ra + sb $t2, 2($a0) +tile00000011: + or $t0, $t0, $a2 + sb $t0, 0($a0) +tile00000010: + or $t1, $t1, $a2 + jr $ra + sb $t1, 1($a0) +tile00000001: + or $t0, $t0, $a2 + jr $ra + sb $t0, 0($a0) + +.data +.align 4 + +TileTable: + .long 000000000000, tile00000001, tile00000010, tile00000011, tile00000100, tile00000101, tile00000110, tile00000111 + .long tile00001000, tile00001001, tile00001010, tile00001011, tile00001100, tile00001101, tile00001110, tile00001111 + .long tile00010000, tile00010001, tile00010010, tile00010011, tile00010100, tile00010101, tile00010110, tile00010111 + .long tile00011000, tile00011001, tile00011010, tile00011011, tile00011100, tile00011101, tile00011110, tile00011111 + .long tile00100000, tile00100001, tile00100010, tile00100011, tile00100100, tile00100101, tile00100110, tile00100111 + .long tile00101000, tile00101001, tile00101010, tile00101011, tile00101100, tile00101101, tile00101110, tile00101111 + .long tile00110000, tile00110001, tile00110010, tile00110011, tile00110100, tile00110101, tile00110110, tile00110111 + .long tile00111000, tile00111001, tile00111010, tile00111011, tile00111100, tile00111101, tile00111110, tile00111111 + .long tile01000000, tile01000001, tile01000010, tile01000011, tile01000100, tile01000101, tile01000110, tile01000111 + .long tile01001000, tile01001001, tile01001010, tile01001011, tile01001100, tile01001101, tile01001110, tile01001111 + .long tile01010000, tile01010001, tile01010010, tile01010011, tile01010100, tile01010101, tile01010110, tile01010111 + .long tile01011000, tile01011001, tile01011010, tile01011011, tile01011100, tile01011101, tile01011110, tile01011111 + .long tile01100000, tile01100001, tile01100010, tile01100011, tile01100100, tile01100101, tile01100110, tile01100111 + .long tile01101000, tile01101001, tile01101010, tile01101011, tile01101100, tile01101101, tile01101110, tile01101111 + .long tile01110000, tile01110001, tile01110010, tile01110011, tile01110100, tile01110101, tile01110110, tile01110111 + .long tile01111000, tile01111001, tile01111010, tile01111011, tile01111100, tile01111101, tile01111110, tile01111111 + .long tile10000000, tile10000001, tile10000010, tile10000011, tile10000100, tile10000101, tile10000110, tile10000111 + .long tile10001000, tile10001001, tile10001010, tile10001011, tile10001100, tile10001101, tile10001110, tile10001111 + .long tile10010000, tile10010001, tile10010010, tile10010011, tile10010100, tile10010101, tile10010110, tile10010111 + .long tile10011000, tile10011001, tile10011010, tile10011011, tile10011100, tile10011101, tile10011110, tile10011111 + .long tile10100000, tile10100001, tile10100010, tile10100011, tile10100100, tile10100101, tile10100110, tile10100111 + .long tile10101000, tile10101001, tile10101010, tile10101011, tile10101100, tile10101101, tile10101110, tile10101111 + .long tile10110000, tile10110001, tile10110010, tile10110011, tile10110100, tile10110101, tile10110110, tile10110111 + .long tile10111000, tile10111001, tile10111010, tile10111011, tile10111100, tile10111101, tile10111110, tile10111111 + .long tile11000000, tile11000001, tile11000010, tile11000011, tile11000100, tile11000101, tile11000110, tile11000111 + .long tile11001000, tile11001001, tile11001010, tile11001011, tile11001100, tile11001101, tile11001110, tile11001111 + .long tile11010000, tile11010001, tile11010010, tile11010011, tile11010100, tile11010101, tile11010110, tile11010111 + .long tile11011000, tile11011001, tile11011010, tile11011011, tile11011100, tile11011101, tile11011110, tile11011111 + .long tile11100000, tile11100001, tile11100010, tile11100011, tile11100100, tile11100101, tile11100110, tile11100111 + .long tile11101000, tile11101001, tile11101010, tile11101011, tile11101100, tile11101101, tile11101110, tile11101111 + .long tile11110000, tile11110001, tile11110010, tile11110011, tile11110100, tile11110101, tile11110110, tile11110111 + .long tile11111000, tile11111001, tile11111010, tile11111011, tile11111100, tile11111101, tile11111110, tile11111111 + + diff --git a/platform/ps2/Memory_mips_r5900.s b/platform/ps2/Memory_mips_r5900.s new file mode 100644 index 00000000..fcd3c289 --- /dev/null +++ b/platform/ps2/Memory_mips_r5900.s @@ -0,0 +1,847 @@ +# vim:filetype=mips + +# memory handlers with banking support for SSF II - The New Challengers +# mostly based on Gens code +# For the MIPS R5900. Based on Memory_amips.s by Notaz. + +# (c) Copyright 2007, Grazvydas "notaz" Ignotas +# All Rights Reserved + + +.set noreorder +.set noat #$at is currently used in the substitute macro instructions (and some replacement code). + +.text +.align 4 + +.macro ext dest,src,pos,size + srl \dest, \src, \pos + li $at, ((1 << \size) - 1) + and \dest, $at +.endm + +# default jump tables + +m_read8_def_table: + .long m_read8_rom0 # 0x000000 - 0x07FFFF + .long m_read8_rom1 # 0x080000 - 0x0FFFFF + .long m_read8_rom2 # 0x100000 - 0x17FFFF + .long m_read8_rom3 # 0x180000 - 0x1FFFFF + .long m_read8_rom4 # 0x200000 - 0x27FFFF + .long m_read8_rom5 # 0x280000 - 0x2FFFFF + .long m_read8_rom6 # 0x300000 - 0x37FFFF + .long m_read8_rom7 # 0x380000 - 0x3FFFFF + .long m_read8_rom8 # 0x400000 - 0x47FFFF - for all those large ROM hacks + .long m_read8_rom9 # 0x480000 - 0x4FFFFF + .long m_read8_romA # 0x500000 - 0x57FFFF + .long m_read8_romB # 0x580000 - 0x5FFFFF + .long m_read8_romC # 0x600000 - 0x67FFFF + .long m_read8_romD # 0x680000 - 0x6FFFFF + .long m_read8_romE # 0x700000 - 0x77FFFF + .long m_read8_romF # 0x780000 - 0x7FFFFF + .long m_read8_rom10 # 0x800000 - 0x87FFFF + .long m_read8_rom11 # 0x880000 - 0x8FFFFF + .long m_read8_rom12 # 0x900000 - 0x97FFFF + .long m_read8_rom13 # 0x980000 - 0x9FFFFF + .long m_read8_misc # 0xA00000 - 0xA7FFFF + .long m_read_null # 0xA80000 - 0xAFFFFF + .long m_read_null # 0xB00000 - 0xB7FFFF + .long m_read_null # 0xB80000 - 0xBFFFFF + .long m_read8_vdp # 0xC00000 - 0xC7FFFF + .long m_read8_vdp # 0xC80000 - 0xCFFFFF + .long m_read8_vdp # 0xD00000 - 0xD7FFFF + .long m_read8_vdp # 0xD80000 - 0xDFFFFF + .long m_read8_ram # 0xE00000 - 0xE7FFFF + .long m_read8_ram # 0xE80000 - 0xEFFFFF + .long m_read8_ram # 0xF00000 - 0xF7FFFF + .long m_read8_ram # 0xF80000 - 0xFFFFFF + +m_read16_def_table: + .long m_read16_rom0 # 0x000000 - 0x07FFFF + .long m_read16_rom1 # 0x080000 - 0x0FFFFF + .long m_read16_rom2 # 0x100000 - 0x17FFFF + .long m_read16_rom3 # 0x180000 - 0x1FFFFF + .long m_read16_rom4 # 0x200000 - 0x27FFFF + .long m_read16_rom5 # 0x280000 - 0x2FFFFF + .long m_read16_rom6 # 0x300000 - 0x37FFFF + .long m_read16_rom7 # 0x380000 - 0x3FFFFF + .long m_read16_rom8 # 0x400000 - 0x47FFFF + .long m_read16_rom9 # 0x480000 - 0x4FFFFF + .long m_read16_romA # 0x500000 - 0x57FFFF + .long m_read16_romB # 0x580000 - 0x5FFFFF + .long m_read16_romC # 0x600000 - 0x67FFFF + .long m_read16_romD # 0x680000 - 0x6FFFFF + .long m_read16_romE # 0x700000 - 0x77FFFF + .long m_read16_romF # 0x780000 - 0x7FFFFF + .long m_read16_rom10 # 0x800000 - 0x87FFFF + .long m_read16_rom11 # 0x880000 - 0x8FFFFF + .long m_read16_rom12 # 0x900000 - 0x97FFFF + .long m_read16_rom13 # 0x980000 - 0x9FFFFF + .long m_read16_misc # 0xA00000 - 0xA7FFFF + .long m_read_null # 0xA80000 - 0xAFFFFF + .long m_read_null # 0xB00000 - 0xB7FFFF + .long m_read_null # 0xB80000 - 0xBFFFFF + .long m_read16_vdp # 0xC00000 - 0xC7FFFF + .long m_read16_vdp # 0xC80000 - 0xCFFFFF + .long m_read16_vdp # 0xD00000 - 0xD7FFFF + .long m_read16_vdp # 0xD80000 - 0xDFFFFF + .long m_read16_ram # 0xE00000 - 0xE7FFFF + .long m_read16_ram # 0xE80000 - 0xEFFFFF + .long m_read16_ram # 0xF00000 - 0xF7FFFF + .long m_read16_ram # 0xF80000 - 0xFFFFFF + +m_read32_def_table: + .long m_read32_rom0 # 0x000000 - 0x07FFFF + .long m_read32_rom1 # 0x080000 - 0x0FFFFF + .long m_read32_rom2 # 0x100000 - 0x17FFFF + .long m_read32_rom3 # 0x180000 - 0x1FFFFF + .long m_read32_rom4 # 0x200000 - 0x27FFFF + .long m_read32_rom5 # 0x280000 - 0x2FFFFF + .long m_read32_rom6 # 0x300000 - 0x37FFFF + .long m_read32_rom7 # 0x380000 - 0x3FFFFF + .long m_read32_rom8 # 0x400000 - 0x47FFFF + .long m_read32_rom9 # 0x480000 - 0x4FFFFF + .long m_read32_romA # 0x500000 - 0x57FFFF + .long m_read32_romB # 0x580000 - 0x5FFFFF + .long m_read32_romC # 0x600000 - 0x67FFFF + .long m_read32_romD # 0x680000 - 0x6FFFFF + .long m_read32_romE # 0x700000 - 0x77FFFF + .long m_read32_romF # 0x780000 - 0x7FFFFF + .long m_read32_rom10 # 0x800000 - 0x87FFFF + .long m_read32_rom11 # 0x880000 - 0x8FFFFF + .long m_read32_rom12 # 0x900000 - 0x97FFFF + .long m_read32_rom13 # 0x980000 - 0x9FFFFF + .long m_read32_misc # 0xA00000 - 0xA7FFFF + .long m_read_null # 0xA80000 - 0xAFFFFF + .long m_read_null # 0xB00000 - 0xB7FFFF + .long m_read_null # 0xB80000 - 0xBFFFFF + .long m_read32_vdp # 0xC00000 - 0xC7FFFF + .long m_read32_vdp # 0xC80000 - 0xCFFFFF + .long m_read32_vdp # 0xD00000 - 0xD7FFFF + .long m_read32_vdp # 0xD80000 - 0xDFFFFF + .long m_read32_ram # 0xE00000 - 0xE7FFFF + .long m_read32_ram # 0xE80000 - 0xEFFFFF + .long m_read32_ram # 0xF00000 - 0xF7FFFF + .long m_read32_ram # 0xF80000 - 0xFFFFFF + + +# ############################################################################# + +.bss +.align 4 + +# used tables +m_read8_table: + .skip 32*4 + +m_read16_table: + .skip 32*4 + +m_read32_table: + .skip 32*4 + + +# ############################################################################# + +.text +.align 4 + +.global PicoMemReset +.global PicoRead8 +.global PicoRead16 +.global PicoRead32 +.global PicoWriteRomHW_SSF2 + +.global m_read8_def_table +.global m_read8_table + +.macro PicoMemResetCopyDef dst_table src_table + lui $t0, %hi(\dst_table) + addiu $t0, %lo(\dst_table) + lui $t1, %hi(\src_table) + addiu $t1, %lo(\src_table) + li $t2, 32 +1: + lw $t3, 0($t1) + sw $t3, 0($t0) + addiu $t2, -1 + addiu $t1, 4 + nop #Workaround for the R5900 short-loop bug. + bnez $t2, 1b + addiu $t0, 4 +.endm + +# $t4 = 4 +.macro PicoMemResetRomArea dst_table ar_label + lui $t0, %hi(\dst_table) + addiu $t0, %lo(\dst_table) + lui $t1, %hi(\ar_label) + addiu $t1, %lo(\ar_label) + li $t2, 20 +1: + beq $t2, $v1, 2f + addiu $t2, -1 + sll $t3, $t2, 2 + beq $t2, $t4, 1b # do not touch the SRAM area + addu $t3, $t0 + j 1b + sw $t1, 0($t3) +2: +.endm + + +PicoMemReset: + lui $v1, %hi(Pico+0x22204) + lw $v1, %lo(Pico+0x22204)($v1) # romsize + lui $t0, 8 + addu $v1, $t0 + addiu $v1, -1 + srl $v1, 19 + + PicoMemResetCopyDef m_read8_table m_read8_def_table + PicoMemResetCopyDef m_read16_table m_read16_def_table + PicoMemResetCopyDef m_read32_table m_read32_def_table + + # update memhandlers according to ROM size + li $t4, 4 + PicoMemResetRomArea m_read8_table m_read8_above_rom + PicoMemResetRomArea m_read16_table m_read16_above_rom + PicoMemResetRomArea m_read32_table m_read32_above_rom + + jr $ra + nop + +# ############################################################################# + +.macro PicoReadJump table + lui $t0, %hi(\table) + srl $t1, $a0, 19 + li $at, 0xFFFFFF83 + and $t0, $t0, $at + andi $t1, $t1, 0x1F + sll $t1, $t1, 2 + or $t0, $t0, $t1 + + lw $t0, %lo(\table)($t0) + sll $a0, $a0, 8 + jr $t0 + srl $a0, $a0, 8 +.endm + +PicoRead8: # u32 a + PicoReadJump m_read8_table + +PicoRead16: # u32 a + PicoReadJump m_read16_table + +PicoRead32: # u32 a + PicoReadJump m_read32_table + +# ############################################################################# + +m_read_null: + jr $ra + li $v0, 0 + +m_read_neg1: + jr $ra + addiu $v0, $0, 0xffff + +# loads &Pico.rom to $t3 +.macro m_read_rom_try_sram is200000 size + lui $t2, %hi(SRam) + addiu $t2, %lo(SRam) + lui $t3, %hi(Pico+0x22200) + lw $t1, 8($t2) # SRam.end +.if \is200000 + sll $a0, $a0, 13 + srl $a0, $a0, 13 + lui $t4, 0x20 + or $a0, $t4 +.endif + subu $t4, $a0, $t1 + bgtz $t4, 1f + addiu $t3, %lo(Pico+0x22200) + lw $t1, 4($t2) # SRam.start + subu $t4, $t1, $a0 + bgtz $t4, 1f + nop + lb $t1, 0x11($t3) # Pico.m.sram_reg + andi $t4, $t1, 5 + beqz $t4, 1f + nop +.if \size == 8 + j SRAMRead + nop +.elseif \size == 16 + sd $ra, -16($sp) + jal SRAMRead16 + addiu $sp, -16 + ld $ra, 0($sp) + jr $ra + addiu $sp, 16 +.else + addiu $sp, -32 + sd $ra, 0($sp) + sd $a0, 16($sp) + jal SRAMRead16 + nop + ld $a0, 16($sp) + sd $v0, 16($sp) + jal SRAMRead16 + addiu $a0, 2 + ld $v1, 16($sp) + ld $ra, 0($sp) + andi $v0, $v0, 0xFFFF + srl $v1, $v1, 16 + or $v0, $v1 + jr $ra + addiu $sp, 32 +.endif +# m_read_nosram: +1: +.endm + +.macro m_read8_rom sect + lui $t0, %hi(Pico+0x22200) + lw $t0, %lo(Pico+0x22200)($t0) # rom + xori $a0, 1 + sll $a0, $a0, 13 + srl $a0, $a0, 13 +.if \sect + lui $t1, 8*\sect + addu $a0, $t1 +.endif + addu $t0, $a0 + jr $ra + lb $v0, 0($t0) +.endm + + +m_read8_rom0: # 0x000000 - 0x07ffff + m_read8_rom 0 + +m_read8_rom1: # 0x080000 - 0x0fffff + m_read8_rom 1 + +m_read8_rom2: # 0x100000 - 0x17ffff + m_read8_rom 2 + +m_read8_rom3: # 0x180000 - 0x1fffff + m_read8_rom 3 + +m_read8_rom4: # 0x200000 - 0x27ffff, SRAM area + m_read_rom_try_sram 1 8 + lw $t1, 4($t3) # romsize + subu $t4, $t1, $a0 + blez $t4, m_read_null + lw $t1, 0($t3) # rom + xori $a0, 1 + addu $t1, $a0 + jr $ra + lb $v0, 0($t1) + +m_read8_rom5: # 0x280000 - 0x2fffff + m_read8_rom 5 + +m_read8_rom6: # 0x300000 - 0x37ffff + m_read8_rom 6 + +m_read8_rom7: # 0x380000 - 0x3fffff + m_read8_rom 7 + +m_read8_rom8: # 0x400000 - 0x47ffff + m_read8_rom 8 + +m_read8_rom9: # 0x480000 - 0x4fffff + m_read8_rom 9 + +m_read8_romA: # 0x500000 - 0x57ffff + m_read8_rom 0xA + +m_read8_romB: # 0x580000 - 0x5fffff + m_read8_rom 0xB + +m_read8_romC: # 0x600000 - 0x67ffff + m_read8_rom 0xC + +m_read8_romD: # 0x680000 - 0x6fffff + m_read8_rom 0xD + +m_read8_romE: # 0x700000 - 0x77ffff + m_read8_rom 0xE + +m_read8_romF: # 0x780000 - 0x7fffff + m_read8_rom 0xF + +m_read8_rom10: # 0x800000 - 0x87ffff + m_read8_rom 0x10 + +m_read8_rom11: # 0x880000 - 0x8fffff + m_read8_rom 0x11 + +m_read8_rom12: # 0x900000 - 0x97ffff + m_read8_rom 0x12 + +m_read8_rom13: # 0x980000 - 0x9fffff + m_read8_rom 0x13 + + +m_read8_misc: + srl $t0, $a0, 5 + sll $t0, $t0, 5 + lui $t1, 0xa1 + bne $t0, $t1, m_read8_misc2 + andi $t0, $a0, 0x1e +m_read8_misc_io: + beqz $t0, m_read8_misc_hwreg + sub $t1, $t0, 4 + bgtz $t1, m_read8_misc_ioports + nop + slti $a0, $t0, 4 + xori $a0, 1 + j PadRead + nop + +m_read8_misc_hwreg: + lui $v0, %hi(Pico+0x2220f) + jr $ra + lb $v0, %lo(Pico+0x2220f)($v0) + +m_read8_misc_ioports: + lui $v0, %hi(Pico+0x22000) + sra $v0, $v0, 5 + sll $v0, $v0, 5 + andi $t0, $t0, 0x1F + or $v0, $v0, $t0 + jr $ra + lb $v0, %lo(Pico+0x22000)($v0) + +m_read8_misc2: + lui $t0, 0xa1 + ori $t0, 0x1100 + bne $a0, $t0, m_read8_misc3 + srl $t0, $a0, 16 + j z80ReadBusReq + +m_read8_misc3: + addiu $t0, 0xff60 # expecting 0xa0 to get 0 + bnez $t0, m_read8_misc4 + + # z80 area + andi $t0, $a0, 0x4000 + bnez $t0, m_read8_z80_misc + andi $t0, $a0, 0x6000 + j z80Read8 # z80 RAM + +m_read8_z80_misc: + addiu $t0, 0xc000 # expecting 0x4000 to get 0 + bnez $t0, m_read_neg1 # invalid + nop + j ym2612_read_local_68k + nop + +m_read8_fake_ym2612: + lb $v0, %lo(Pico+0x22208)($t0) # Pico.m.rotate + addiu $t1, $v0, 1 + jr $ra + sb $t1, %lo(Pico+0x22208)($t0) + +# delay slot friendly +.macro m_read8_call16 funcname is_func_ptr=0 +.if \is_func_ptr + lui $t1, %hi(\funcname) + lw $t1, %lo(\funcname)($t1) +.endif + andi $t0, $a0, 1 + beqz $t0, 1f + li $a1, 8 # not always needed, but shouln't cause problems +.if \is_func_ptr + jr $t1 +.else + j \funcname # odd address +.endif + nop +1: + addiu $sp, -16 + sd $ra, 0($sp) +.if \is_func_ptr + jalr $t1 +.else + jal \funcname +.endif + xori $a0, 1 + ld $ra, 0($sp) + addiu $sp, 16 + jr $ra + srl $v0, 8 +.endm + +m_read8_misc4: + # if everything else fails, use generic handler + m_read8_call16 OtherRead16 + +m_read8_vdp: + ext $t0, $a0, 16, 3 + andi $t1, $a0, 0xe0 + or $t0, $t1 + bnez $t0, m_read_null # invalid address + nop + j PicoVideoRead8 + nop + +m_read8_ram: + lui $t0, %hi(Pico) + andi $a0, $a0, 0xFFFF + sra $t0, $t0, 16 + sll $t0, $t0, 16 + or $t0, $t0, $a0 + xori $t0, 1 + jr $ra + lb $v0, %lo(Pico)($t0) + +m_read8_above_rom: + # might still be SRam (Micro Machines, HardBall '95) + m_read_rom_try_sram 0 8 + m_read8_call16 PicoRead16Hook 1 + +# ############################################################################# + +.macro m_read16_rom sect + lui $t0, %hi(Pico+0x22200) + lw $t0, %lo(Pico+0x22200)($t0) # rom + li $at, 0x0007FFFE + and $a0, $a0, $at +.if \sect + lui $t1, 8*\sect + addu $a0, $t1 +.endif + addu $t0, $a0 + jr $ra + lh $v0, 0($t0) +.endm + + +m_read16_rom0: # 0x000000 - 0x07ffff + m_read16_rom 0 + +m_read16_rom1: # 0x080000 - 0x0fffff + m_read16_rom 1 + +m_read16_rom2: # 0x100000 - 0x17ffff + m_read16_rom 2 + +m_read16_rom3: # 0x180000 - 0x1fffff + m_read16_rom 3 + +m_read16_rom4: # 0x200000 - 0x27ffff, SRAM area + m_read_rom_try_sram 1 16 + lw $t1, 4($t3) # romsize + subu $t4, $t1, $a0 + blez $t4, m_read_null + lw $t1, 0($t3) # rom + sra $a0, $a0, 1 + sll $a0, $a0, 1 + addu $t1, $a0 + jr $ra + lh $v0, 0($t1) + +m_read16_rom5: # 0x280000 - 0x2fffff + m_read16_rom 5 + +m_read16_rom6: # 0x300000 - 0x37ffff + m_read16_rom 6 + +m_read16_rom7: # 0x380000 - 0x3fffff + m_read16_rom 7 + +m_read16_rom8: # 0x400000 - 0x47ffff + m_read16_rom 8 + +m_read16_rom9: # 0x480000 - 0x4fffff + m_read16_rom 9 + +m_read16_romA: # 0x500000 - 0x57ffff + m_read16_rom 0xA + +m_read16_romB: # 0x580000 - 0x5fffff + m_read16_rom 0xB + +m_read16_romC: # 0x600000 - 0x67ffff + m_read16_rom 0xC + +m_read16_romD: # 0x680000 - 0x6fffff + m_read16_rom 0xD + +m_read16_romE: # 0x700000 - 0x77ffff + m_read16_rom 0xE + +m_read16_romF: # 0x780000 - 0x7fffff + m_read16_rom 0xF + +m_read16_rom10: # 0x800000 - 0x87ffff + m_read16_rom 0x10 + +m_read16_rom11: # 0x880000 - 0x8fffff + m_read16_rom 0x11 + +m_read16_rom12: # 0x900000 - 0x97ffff + m_read16_rom 0x12 + +m_read16_rom13: # 0x980000 - 0x9fffff + m_read16_rom 0x13 + +m_read16_misc: + sra $a0, $a0, 1 + sll $a0, $a0, 1 + j OtherRead16 + li $a1, 16 + +m_read16_vdp: + ext $t0, $a0, 16, 3 + andi $t1, $a0, 0xe0 + or $t0, $t1 + bnez $t0, m_read_null # invalid address + sra $a0, $a0, 1 + j PicoVideoRead + sll $a0, $a0, 1 + +m_read16_ram: + lui $t0, %hi(Pico) + srl $a0, $a0, 1 + sll $a0, $a0, 17 + srl $a0, $a0, 16 + sra $t0, $t0, 16 + sll $t0, $t0, 16 + or $t0, $t0, $a0 + jr $ra + lh $v0, %lo(Pico)($t0) + +m_read16_above_rom: + # might still be SRam + m_read_rom_try_sram 0 16 + lui $t1, %hi(PicoRead16Hook) + lw $t1, %lo(PicoRead16Hook)($t1) + sra $a0, $a0, 1 + jr $t1 + sll $a0, $a0, 1 + +# ############################################################################# + +.macro m_read32_rom sect + lui $t0, %hi(Pico+0x22200) + lw $t0, %lo(Pico+0x22200)($t0) # rom + li $at, 0x0007FFFE + and $a0, $a0, $at +.if \sect + lui $t1, 8*\sect + addu $a0, $t1 +.endif + addu $t0, $a0 + lh $v1, 0($t0) + lh $v0, 2($t0) + andi $v0, $v0, 0xFFFF + sll $v1, $v1, 16 + jr $ra + or $v0, $v0, $v1 +.endm + + +m_read32_rom0: # 0x000000 - 0x07ffff + m_read32_rom 0 + +m_read32_rom1: # 0x080000 - 0x0fffff + m_read32_rom 1 + +m_read32_rom2: # 0x100000 - 0x17ffff + m_read32_rom 2 + +m_read32_rom3: # 0x180000 - 0x1fffff + m_read32_rom 3 + +m_read32_rom4: # 0x200000 - 0x27ffff, SRAM area + m_read_rom_try_sram 1 32 + lw $t1, 4($t3) # romsize + subu $t4, $t1, $a0 + blez $t4, m_read_null + lw $t1, 0($t3) # rom + sra $a0, $a0, 1 + sll $a0, $a0, 1 + addu $t1, $a0 + lh $v1, 0($t1) + lh $v0, 2($t1) + andi $v0, $v0, 0xFFFF + sll $v1, $v1, 16 + jr $ra + or $v0, $v0, $v1 + +m_read32_rom5: # 0x280000 - 0x2fffff + m_read32_rom 5 + +m_read32_rom6: # 0x300000 - 0x37ffff + m_read32_rom 6 + +m_read32_rom7: # 0x380000 - 0x3fffff + m_read32_rom 7 + +m_read32_rom8: # 0x400000 - 0x47ffff + m_read32_rom 8 + +m_read32_rom9: # 0x480000 - 0x4fffff + m_read32_rom 9 + +m_read32_romA: # 0x500000 - 0x57ffff + m_read32_rom 0xA + +m_read32_romB: # 0x580000 - 0x5fffff + m_read32_rom 0xB + +m_read32_romC: # 0x600000 - 0x67ffff + m_read32_rom 0xC + +m_read32_romD: # 0x680000 - 0x6fffff + m_read32_rom 0xD + +m_read32_romE: # 0x700000 - 0x77ffff + m_read32_rom 0xE + +m_read32_romF: # 0x780000 - 0x7fffff + m_read32_rom 0xF + +m_read32_rom10: # 0x800000 - 0x87ffff + m_read32_rom 0x10 + +m_read32_rom11: # 0x880000 - 0x8fffff + m_read32_rom 0x11 + +m_read32_rom12: # 0x900000 - 0x97ffff + m_read32_rom 0x12 + +m_read32_rom13: # 0x980000 - 0x9fffff + m_read32_rom 0x13 + +.macro m_read32_call16 func need_a1=0 + addiu $sp, -32 + sd $ra, 0($sp) + sd $s0, 16($sp) +.if \need_a1 + li $a1, 16 +.endif + jal \func + move $s0, $a0 + + addu $a0, $s0, 2 +.if \need_a1 + li $a1, 16 +.endif + jal \func + move $s0, $v0 + + sll $s0, $s0, 16 + andi $v0, $v0, 0xFFFF + or $v0, $v0, $s0 + ld $ra, 0($sp) + ld $s0, 16($sp) + jr $ra + addiu $sp, 32 +.endm + +m_read32_misc: + sra $a0, $a0, 1 + sll $a0, $a0, 1 + m_read32_call16 OtherRead16, 1 + +m_read32_vdp: + ext $t0, $a0, 16, 3 + andi $t1, $a0, 0xe0 + or $t0, $t1 + bnez $t0, m_read_null # invalid address + sra $a0, $a0, 1 + sll $a0, $a0, 1 + m_read32_call16 PicoVideoRead + +m_read32_ram: + lui $t0, %hi(Pico) + sra $a0, $a0, 1 + sll $a0, $a0, 17 + srl $a0, $a0, 16 + sra $t0, $t0, 16 + sll $t0, $t0, 16 + or $t0, $t0, $a0 + lh $v1, %lo(Pico)($t0) + lh $v0, %lo(Pico+2)($t0) + andi $v0, $v0, 0xFFFF + sll $v1, $v1, 16 + jr $ra + or $v0, $v0, $v1 + +m_read32_above_rom: + # might still be SRam + m_read_rom_try_sram 0 32 + sra $a0, $a0, 1 + sll $a0, $a0, 1 + lui $t1, %hi(PicoRead16Hook) + lw $t1, %lo(PicoRead16Hook)($t1) + addiu $sp, -16*3 + sd $ra, 0($sp) + sd $s0, 16($sp) + sd $t1, 32($sp) + jalr $t1 + move $s0, $a0 + + ld $t1, 32($sp) + addu $a0, $s0, 2 + jalr $t1 + move $s0, $v0 + + andi $v0, $v0, 0xFFFF + sll $s0, $s0, 16 + or $v0, $v0, $s0 + ld $ra, 0($sp) + ld $s0, 16($sp) + jr $ra + addiu $sp, 16*3 + +# ############################################################################# + +.macro PicoWriteRomHW_SSF2_ls def_table table + lui $t3, %hi(\def_table) + li $at, 0xFFFFFF83 + and $t3, $t3, $at + andi $at, $a1, 0x1F + sll $at, $at, 2 + or $t3, $t3, $at + lw $t0, %lo(\def_table)($t3) + lui $t2, %hi(\table) + li $at, 0xFFFFFFE3 + and $t2, $t2, $at + andi $at, $a0, 0x07 + sll $at, $at, 2 + or $t2, $t2, $at + sw $t0, %lo(\table)($t2) +.endm + +PicoWriteRomHW_SSF2: # u32 a, u32 d + ext $a0, $a0, 1, 3 + bnez $a0, pwr_banking + + # sram register + lui $t0, %hi(Pico+0x22211) + lb $t1, %lo(Pico+0x22211)($t0) # Pico.m.sram_reg + sra $t1, $t1, 2 + sll $t1, $t1, 2 + andi $a1, $a1, 3 + or $t1, $t1, $a1 + jr $ra + sb $t1, %lo(Pico+0x22211)($t0) + +pwr_banking: + andi $a1, 0x1f + + PicoWriteRomHW_SSF2_ls m_read8_def_table m_read8_table + PicoWriteRomHW_SSF2_ls m_read16_def_table m_read16_table + PicoWriteRomHW_SSF2_ls m_read32_def_table m_read32_table + + jr $ra + nop + diff --git a/platform/ps2/SMS_Utils.s b/platform/ps2/SMS_Utils.s new file mode 100644 index 00000000..e4373562 --- /dev/null +++ b/platform/ps2/SMS_Utils.s @@ -0,0 +1,202 @@ +/* +# ___ _ _ ___ +# | | | | | +# ___| | | ___| PS2DEV Open Source Project. +#---------------------------------------------------------- +# MUL64 is pulled from some binary library (I don't remember which one). +# mips_memcpy routine is pulled from 'sde' library from MIPS. +# +*/ +.set noat +.set noreorder +.set nomacro + +.globl MUL64 +.globl mips_memcpy +.globl mips_memset + +.text + +MUL64: + pmultuw $v0, $a0, $a1 + dsra32 $a2, $a0, 0 + dsra32 $v1, $a1, 0 + mult $v1, $a0, $v1 + mult1 $a2, $a2, $a1 + addu $v1, $v1, $a2 + dsll32 $v1, $v1, 0 + jr $ra + daddu $v0, $v0, $v1 + +mips_memcpy: + addu $v0, $a0, $zero + beqz $a2, 1f + sltiu $t2, $a2, 12 + bnez $t2, 2f + xor $v1, $a1, $a0 + andi $v1, $v1, 7 + negu $a3, $a0 + beqz $v1, 3f + andi $a3, $a3, 7 + beqz $a3, 4f + subu $a2, $a2, $a3 + ldr $v1, 0($a1) + ldl $v1, 7($a1) + addu $a1, $a1, $a3 + sdr $v1, 0($a0) + addu $a0, $a0, $a3 +4: + andi $v1, $a2, 31 + subu $a3, $a2, $v1 + beqz $a3, 5f + addu $a2, $v1, $zero + addu $a3, $a3, $a1 +6: + ldr $v1, 0($a1) + ldl $v1, 7($a1) + ldr $t0, 8($a1) + ldl $t0, 15($a1) + ldr $t1, 16($a1) + ldl $t1, 23($a1) + ldr $t2, 24($a1) + ldl $t2, 31($a1) + sd $v1, 0($a0) + sd $t0, 8($a0) + sd $t1, 16($a0) + addiu $a1, $a1, 32 + addiu $a0, $a0, 32 + bne $a1, $a3, 6b + sd $t2, -8($a0) +5: + andi $v1, $a2, 7 + subu $a3, $a2, $v1 + beqz $a3, 2f + addu $a2, $v1, $zero + addu $a3, $a3, $a1 +7: + ldr $v1, 0($a1) + ldl $v1, 7($a1) + addiu $a1, $a1, 8 + addiu $a0, $a0, 8 + nop + bne $a1, $a3, 7b + sd $v1, -8($a0) + beq $zero, $zero, 2f + nop +3: + beqz $a3, 8f + subu $a2, $a2, $a3 + ldr $v1, 0($a1) + addu $a1, $a1, $a3 + sdr $v1, 0($a0) + addu $a0, $a0, $a3 +8: + andi $v1, $a2, 31 + subu $a3, $a2, $v1 + beqz $a3, 9f + addu $a2, $v1, $zero + addu $a3, $a3, $a1 +10: + ld $v1, 0($a1) + ld $t0, 8($a1) + ld $t1, 16($a1) + ld $t2, 24($a1) + sd $v1, 0($a0) + sd $t0, 8($a0) + sd $t1, 16($a0) + addiu $a1, $a1, 32 + addiu $a0, $a0, 32 + bne $a1, $a3, 10b + sd $t2, -8($a0) +9: + andi $v1, $a2, 7 + subu $a3, $a2, $v1 + beqz $a3, 2f + addu $a2, $v1, $zero + addu $a3, $a3, $a1 +11: + ld $v1, 0($a1) + addiu $a1, $a1, 8 + addiu $a0, $a0, 8 + nop + nop + bne $a1, $a3, 11b + sd $v1, -8($a0) +2: + beqz $a2, 1f + addu $a3, $a2, $a1 +12: + lbu $v1, 0($a1) + addiu $a1, $a1, 1 + addiu $a0, $a0, 1 + nop + nop + bne $a1, $a3, 12b + sb $v1, -1($a0) +1: + jr $ra + nop + +mips_memset: + beqz $a2, 1f + sltiu $at, $a2, 16 + bnez $at, 2f + andi $a1, $a1, 0xFF + dsll $at, $a1, 0x8 + or $a1, $a1, $at + dsll $at, $a1, 0x10 + or $a1, $a1, $at + dsll32 $at, $a1, 0x0 + or $a1, $a1, $at + andi $v1, $a0, 0x7 + beqz $v1, 3f + li $a3, 8 + subu $a3, $a3, $v1 + subu $a2, $a2, $a3 + sdr $a1, 0($a0) + addu $a0, $a0, $a3 +3: + andi $v1, $a2, 0x1f + subu $a3, $a2, $v1 + beqz $a3, 4f + move $a2, $v1 + addu $a3, $a3, $a0 +5: + sd $a1, 0($a0) + sd $a1, 8($a0) + sd $a1, 16($a0) + addiu $a0, $a0, 32 + sd $a1, -8($a0) + bne $a0, $a3, 5b +4: + andi $v1, $a2, 0x7 + subu $a3, $a2, $v1 + beqz $a3, 2f + move $a2, $v1 + addu $a3, $a3, $a0 +6: + addiu $a0, $a0, 8 + beq $a0, $a3, 2f + sd $a1, -8($a0) + addiu $a0, $a0, 8 + beq $a0, $a3, 2f + sd $a1, -8($a0) + addiu $a0, $a0, 8 + bne $a0, $a3, 6b + sd $a1, -8($a0) +2: + beqz $a2, 1f + addu $a3, $a2, $a0 +7: + addiu $a0, $a0, 1 + beq $a0, $a3, 1f + sb $a1, -1($a0) + addiu $a0, $a0, 1 + beq $a0, $a3, 1f + sb $a1, -1($a0) + addiu $a0, $a0, 1 + bne $a0, $a3, 7b + sb $a1, -1($a0) +1: + jr $ra + nop diff --git a/platform/ps2/asm.h b/platform/ps2/asm.h new file mode 100644 index 00000000..099ea1f1 --- /dev/null +++ b/platform/ps2/asm.h @@ -0,0 +1,3 @@ +// By right, input and output pointers must be all quad-word aligned. Unfortunately, some stuff that Picodrive passes to these functions aren't aligned to that degree. And so, only double-word alignment is required. +void do_pal_convert(unsigned short *dest, const unsigned short *src); +void do_pal_convert_with_shadows(unsigned short *dest, const unsigned short *src); diff --git a/platform/ps2/asm.s b/platform/ps2/asm.s new file mode 100644 index 00000000..cc7c800a --- /dev/null +++ b/platform/ps2/asm.s @@ -0,0 +1,129 @@ +# vim:filetype=mips + +# some asm utils for the Sony Emotion Engine (MIPS R5900) + +.set push +.set noreorder + +.text +.align 4 + +# A1B5G5R5 abbb bbgg gggr rrrr +.global do_pal_convert # dest, src +.ent do_pal_convert +do_pal_convert: + li $t0, 0x8000800080008000 #A + li $t1, 0x000E000E000E000E #R + li $t2, 0x00E000E000E000E0 #G + li $t3, 0x0E000E000E000E00 #B + li $t4, 64 # 64 16-bit colours + + #Duplicate the lower dword into the upper dword of each mask (0-63 to 64-127). + pcpyld $t0, $t0 + pcpyld $t1, $t1 + pcpyld $t2, $t2 + pcpyld $t3, $t3 + + # I couldn't do this with qword loads and stores in C (There's no 128-bit literal data type definition), but here's the 16-bit (1 colour per literation) equivalent in C for a reference. + # PalRow=in_palette[i]; + # palette[i]=((PalRow&0x000E)<< 1)|((PalRow&0x00E0)<<2)|((PalRow&0x0E00)<<3) | 0x8000; +pal_convert_loop: + ld $t5, 8($a1) + ld $t6, 0($a1) + pcpyld $t5, $t5, $t6 +# lq $t5, 0($a1) #This won't work because the CRAM palette may not be aligned to a 128-bit address (And unless the source code of Picodrive is modified for that purpose, use two dword loads instead). :( + + #Blue + pand $t6, $t5, $t3 + psllh $t6, $t6, 3 + + #Green + pand $t7, $t5, $t2 + psllh $t7, $t7, 2 + + #Red + pand $t5, $t5, $t1 + psllh $t5, $t5, 1 + + por $t5, $t5, $t0 #Logical OR in the alpha channel + por $t5, $t5, $t6 #Logical OR in the blue channel + por $t5, $t5, $t7 #Logical OR in the green channel + + sq $t5, ($a0) + + addiu $a1, $a1, 16 + addiu $t4, $t4, -8 #8 16-bit colours were processed. + bgez $t4, pal_convert_loop + addiu $a0, $a0, 16 + + jr $ra + nop +.end do_pal_convert + +.global do_pal_convert_with_shadows # dest, src +.ent do_pal_convert_with_shadows +do_pal_convert_with_shadows: + li $t0, 0x8000800080008000 #A mask + li $t1, 0x000E000E000E000E #R mask + li $t2, 0x00E000E000E000E0 #G mask + li $t3, 0x0E000E000E000E00 #B mask + li $a2, 0x39CE39CE39CE39CE #Shadow mask + li $a3, 0x4210421042104210 #Highlight mask + li $t4, 64 # 64 16-bit colours + # $t5 will contain the raw converted colour, without alpha. This will be also used for conversion into the shadow alternate colours. + + # Duplicate the lower dword into the upper dword of each mask (0-63 to 64-127). + pcpyld $t0, $t0 + pcpyld $t1, $t1 + pcpyld $t2, $t2 + pcpyld $t3, $t3 + pcpyld $a2, $a2 + pcpyld $a3, $a3 + + # I couldn't do this with qword loads and stores in C (There's no 128-bit literal data type definition), but here's the 16-bit (1 colour per literation) equivalent in C for a reference. + # PalRow=in_palette[i]; + # palette[i]=((PalRow&0x000E)<< 1)|((PalRow&0x00E0)<<2)|((PalRow&0x0E00)<<3) | 0x8000; +pal_convert_loop_sh: + ld $t5, 8($a1) + ld $t6, 0($a1) + pcpyld $t5, $t5, $t6 +# lq $t5, 0($a1) #This won't work because the CRAM palette may not be aligned to a 128-bit address (And unless the source code of Picodrive is modified for that purpose, use two dword loads instead). :( + + #Blue + pand $t6, $t5, $t3 + psllh $t6, $t6, 3 + + #Green + pand $t7, $t5, $t2 + psllh $t7, $t7, 2 + + #Red + pand $t5, $t5, $t1 + psllh $t5, $t5, 1 + + por $t5, $t5, $t6 #Logical OR in the blue channel + por $t5, $t5, $t7 #Logical OR in the green channel + por $t6, $t5, $t0 #Logical OR in the alpha channel + sq $t6, ($a0) #Normal + + #Highlights + por $t6, $t6, $a3 + sq $t6, 0x80($a0) + + #Shadows + psrlh $t5, $t5, 1 + pand $t5, $t5, $a2 + por $t5, $t5, $t0 #Logical OR in the alpha channel + sq $t5, 0x40($a0) + sq $t5, 0xC0($a0) + + addiu $a1, $a1, 16 + addiu $t4, $t4, -8 #8 16-bit colours were processed. + bgez $t4, pal_convert_loop_sh + addiu $a0, $a0, 16 + + jr $ra + nop +.end do_pal_convert_with_shadows + +.set pop