diff --git a/arm9/source/patches/platform/supercard/SuperCardCommon.h b/arm9/source/patches/platform/supercard/SuperCardCommon.h index 8931f39..b0649b8 100644 --- a/arm9/source/patches/platform/supercard/SuperCardCommon.h +++ b/arm9/source/patches/platform/supercard/SuperCardCommon.h @@ -6,8 +6,8 @@ DEFINE_SECTION_SYMBOLS(scsd_change_mode); DEFINE_SECTION_SYMBOLS(scsd_common); extern "C" void sccmn_changeMode(); - extern "C" void sccmn_sdSendClock10(); + extern "C" void sccmn_sdio4BitCrc16(); class SuperCardChangeModePatchCode : public PatchCode @@ -20,6 +20,11 @@ public: { return GetAddressAtTarget((void*)sccmn_changeMode); } + + const void* GetSdSendClock10Function() const + { + return GetAddressAtTarget((void*)sccmn_sdSendClock10); + } }; class SuperCardCommonPatchCode : public PatchCode @@ -28,11 +33,6 @@ public: explicit SuperCardCommonPatchCode(PatchHeap& patchHeap) : PatchCode(SECTION_START(scsd_common), SECTION_SIZE(scsd_common), patchHeap) { } - const void* GetSdSendClock10Function() const - { - return GetAddressAtTarget((void*)sccmn_sdSendClock10); - } - const void* GetCrc16ChecksumFunction() const { return GetAddressAtTarget((void*)sccmn_sdio4BitCrc16); diff --git a/arm9/source/patches/platform/supercard/SuperCardCommon.s b/arm9/source/patches/platform/supercard/SuperCardCommon.s index 48911df..549dbc4 100644 --- a/arm9/source/patches/platform/supercard/SuperCardCommon.s +++ b/arm9/source/patches/platform/supercard/SuperCardCommon.s @@ -8,6 +8,7 @@ @ void sc_change_mode(uint16_t mode); BEGIN_THUMB_FUNCTION sccmn_changeMode + push {r0-r3,lr} ldr r2,= 0x09FFFFFE ldr r3,= 0xA55A strh r3, [r2] @@ -19,24 +20,26 @@ BEGIN_THUMB_FUNCTION sccmn_changeMode @ if mode is 3 (sd enable), reset the sd card @ SDResetCard @ write 0 - ldr r2,= sd_resetaddr + ldr r2, =sd_resetaddr strh r2, [r2] 1: - mov pc, lr + pop {r0-r3,pc} -.section "scsd_common", "ax" -@ this function will trash r4 but leave r0 and r1 untouched @ void SDSendClock10(void) BEGIN_THUMB_FUNCTION sccmn_sdSendClock10 + @ here we get lr from the caller + push {r0-r3} movs r3, #0x10 @ loads reg_scsd_cmd movs r2, #0x98 lsls r2, r2, #20 1: - ldrh r4, [r2] + ldrh r0, [r2] subs r3, r3, #1 bne 1b - mov pc, lr + pop {r0-r3,pc} + +.section "scsd_common", "ax" @ static uint64_t inline calSingleCRC16(uint64_t crc, uint32_t data_in){ @ // Shift out 8 bits for each line @@ -73,8 +76,10 @@ BEGIN_THUMB_FUNCTION sccmn_sdSendClock10 @ uint64_t sdio_crc16_4bit_checksum(void*) @ r0 and r1 are left untouched, the result is returned in r2-r3 instead +@ a "continuation function" is provided in r5, and we have to jump to it BEGIN_THUMB_FUNCTION sccmn_sdio4BitCrc16 - push {r0,r1,r4-r5,lr} + push {r5,lr} + push {r0,r1,r4-r5} movs r4, #0 @ r4 = crc_lo movs r5, #0 @ r5 = crc_hi movs r1, #128 @@ -116,7 +121,7 @@ byteSwap32: push {r0,r1,r4-r5,lr} byteSwap32_nopush: movs r5, #16 - ldr r4,= 0xFF00FF + ldr r4, =0xFF00FF rors r2, r5 // ror 16 ands r4, r2 bics r2, r4 diff --git a/arm9/source/patches/platform/supercard/sclite/SuperCardLiteImpl.h b/arm9/source/patches/platform/supercard/sclite/SuperCardLiteImpl.h index 1948278..525ba6e 100644 --- a/arm9/source/patches/platform/supercard/sclite/SuperCardLiteImpl.h +++ b/arm9/source/patches/platform/supercard/sclite/SuperCardLiteImpl.h @@ -83,7 +83,7 @@ public: INTERWORK_LABEL(sclite_sdCommandAndDropResponse6, readInterwork) = (u32)superCardSdCommandAndDropLitePatchCode->GetSdCommandAndDropResponse6Function(); INTERWORK_LABEL(sclite_readData, readInterwork) = (u32)superCardReadDataLitePatchCode->GetReadDataLiteFunction(); - INTERWORK_LABEL(sccmn_sdSendClock10, readInterwork) = (u32)superCardCommonPatchCode->GetSdSendClock10Function(); + INTERWORK_LABEL(sccmn_sdSendClock10, readInterwork) = (u32)superCardChangeModePatchCode->GetSdSendClock10Function(); } const ReadSectorsFunc GetReadSectorsFunction() const override @@ -104,7 +104,7 @@ public: { INTERWORK_LABEL(sclite_writeData, writeInterwork) = (u32)superCardWriteDataLitePatchCode->GetWriteDataLiteFunction(); INTERWORK_LABEL(sccmn_sdio4BitCrc16, writeInterwork) = (u32)superCardCommonPatchCode->GetCrc16ChecksumFunction(); - INTERWORK_LABEL(sccmn_sdSendClock10, writeInterwork) = (u32)superCardCommonPatchCode->GetSdSendClock10Function(); + INTERWORK_LABEL(sccmn_sdSendClock10, writeInterwork) = (u32)superCardChangeModePatchCode->GetSdSendClock10Function(); INTERWORK_LABEL(sccmn_changeMode, writeInterwork) = (u32)superCardChangeModePatchCode->GetScChangeModeFunction(); INTERWORK_LABEL(sclite_sdCommandAndDropResponse6, writeInterwork) = (u32)superCardSdCommandAndDropLitePatchCode->GetSdCommandAndDropResponse6Function(); diff --git a/arm9/source/patches/platform/supercard/sclite/SuperCardLiteImpl.s b/arm9/source/patches/platform/supercard/sclite/SuperCardLiteImpl.s index cb565fc..b288498 100644 --- a/arm9/source/patches/platform/supercard/sclite/SuperCardLiteImpl.s +++ b/arm9/source/patches/platform/supercard/sclite/SuperCardLiteImpl.s @@ -40,12 +40,19 @@ .section "sclite_sd_command_drop", "ax" @ void sclite_sdCommandAndDropResponse6(uint32_t dummy, uint32_t argument, SD_COMMANDS command) -@ command is passed in r2 +@ command is passed in r2, in r6 is the pointer to sccmn_sdSendClock10 BEGIN_THUMB_FUNCTION sclite_sdCommandAndDropResponse6 + push {lr} + cmp r2, #0x52 + @ if command is READ_MULTIPLE_BLOCK, don't send extra clock cycles + beq 1f + @ we need to call sccmn_sdSendClock10 after the command is sent, push sccmn_sdSendClock10 and the lr to the stack + push {r6} +1: @ among the pushed registers there are the command and @ argument one, which are then used at the loop to @ send the sd command - push {r1-r7,lr} + push {r1-r7} @ loads reg_scsd_cmd movs r7, #0x98 @@ -100,8 +107,11 @@ SDCommand_drop_resp: subs r6, r6, #1 bne SDCommand_drop_resp - @ restore stack space + @ we pop from the stack r6 as pc, which corresponds to sccmn_sdSendClock10 or lr, if it is sccmn_sdSendClock10 that function + @ is called, and that function doesn't push a new lr but pops a preexisting one from the stack, which in our case is the + @ lr provided to this function pop {r1-r7,pc} + .balign 4 .pool @@ -110,7 +120,7 @@ SDCommand_drop_resp: BEGIN_THUMB_FUNCTION sclite_writeSector push {r1,r2,r4-r7,lr} - @ load EXMEMCNT register + @ load EXMEMCNT register into r7 LOAD_EXMEMCNT @ r1 for now holds the sector @@ -120,80 +130,96 @@ sclite_writeSectorSdhcLabel: lsls r1, r0, #9 @ movs r1, r0 + @ r4 sccmn_changeMode + @ r5 sclite_sdCommandAndDropResponse6 + @ r6 sccmn_sdSendClock10 + + adr r3, sccmn_changeMode_writeInterworkLite_address + ldmia r3!, {r4-r6} + @ enable sd access - @ this function won't touch r1 + @ this function won't touch anything movs r0, #3 - CALL sccmn_changeMode writeInterwork + @ call sccmn_changeMode + bl interwork_r4 @ WRITE_MULTIPLE_BLOCK + @ puts the value in r2 SD_COMMAND_ARGUMENT #25 @ 2nd parameter is in r1 from above - CALL sclite_sdCommandAndDropResponse6 writeInterwork + @ call sclite_sdCommandAndDropResponse6 + bl interwork_r5 - @ this function will trash r4 but leave r0 and r1 untouched - CALL sccmn_sdSendClock10 writeInterwork + @ load the rest of the functions + @ r4 sccmn_sdio4BitCrc16 + @ r5 sclite_writeData + ldmia r3!, {r4-r5} - @ loads the saved r0 and r2 (readnum) + @ loads the saved r1 (buff) and r2 (writenum) @ into r0 and r1 pop {r0,r1} + write_sector_loop: - @ all the functions called in this loop don't change the value of r0 and r1 + @ all the functions called in this loop don't change the value of any register @ except sclite_writeData, which will increase r0 by 512 @ sccmn_sdio4BitCrc16 will write the checksum to r2-r3 - CALL sccmn_sdio4BitCrc16 writeInterwork - - @ first argument is buffer - @ regs r2 and r3 hold the crc - CALL sclite_writeData writeInterwork - - @ this function will trash r4 but leave r0 and r1 untouched - CALL sccmn_sdSendClock10 writeInterwork + @ call sccmn_sdio4BitCrc16, this function will then tail call to r5 (sclite_writeData) + bl interwork_r4 subs r1, #1 bne write_sector_loop + adr r3, sccmn_changeMode_writeInterworkLite_address + @ r4 sccmn_changeMode + @ r5 sclite_sdCommandAndDropResponse6 + ldmia r3!, {r4-r5} + @ STOP_TRANSMISSION + @ puts the value in r2 SD_COMMAND_ARGUMENT #12 @ 2nd parameter is passed in r1 @ and from the loop above r1 is already 0 - CALL sclite_sdCommandAndDropResponse6 writeInterwork - - @ this function will trash r4 but leave r0 and r1 untouched - CALL sccmn_sdSendClock10 writeInterwork + @ call sclite_sdCommandAndDropResponse6 + bl interwork_r5 @ loads sd_dataadd movs r0, #0x90 lsls r0, r0, #20 - @ while(*r1 &0x100) == 0 + @ while(*r0 &0x100) == 0 beginwhile_WriteSector: ldrh r1, [r0] lsrs r1, #9 bcc beginwhile_WriteSector movs r0, #1 - CALL sccmn_changeMode writeInterwork + @ call sccmn_changeMode writeInterwork + bl interwork_r4 @ restore EXMEMCNT register RESTORE_EXMEMCNT pop {r4-r7,pc} -INTERWORK writeInterwork -INTERWORK_FUNCTION sclite_writeData writeInterwork -INTERWORK_FUNCTION sccmn_sdio4BitCrc16 writeInterwork -INTERWORK_FUNCTION sccmn_sdSendClock10 writeInterwork -INTERWORK_FUNCTION sccmn_changeMode writeInterwork -INTERWORK_FUNCTION sclite_sdCommandAndDropResponse6 writeInterwork - +interwork_r4: + bx r4 +interwork_r5: + bx r5 .balign 4 .pool +INTERWORK_FUNCTION sccmn_changeMode writeInterwork +INTERWORK_FUNCTION sclite_sdCommandAndDropResponse6 writeInterwork +INTERWORK_FUNCTION sccmn_sdSendClock10 writeInterwork +INTERWORK_FUNCTION sccmn_sdio4BitCrc16 writeInterwork +INTERWORK_FUNCTION sclite_writeData writeInterwork .section "sclite_read_sector", "ax" @ bool sclite_readSector(uint32_t sector, uint8_t *buff, uint32_t readnum) BEGIN_THUMB_FUNCTION sclite_readSector push {r1,r2-r7,lr} + + @ load EXMEMCNT register into r7 LOAD_EXMEMCNT @ r1 for now holds the sector @@ -204,21 +230,22 @@ sclite_readSectorSdhcLabel: @ movs r1, r0 @ enable sd access - @ this function won't touch r1 + @ this function won't touch anything movs r0, #3 CALL sccmn_changeMode readInterwork @ READ_MULTIPLE_BLOCK + @ puts the value in r2 SD_COMMAND_ARGUMENT #18 @ 2nd parameter is in r1 from above CALL sclite_sdCommandAndDropResponse6 readInterwork - @ loads the saved r0 and r2 (writenum) + @ loads the saved r1 (buff) and r2 (readnum) @ into r0 and r1 pop {r0,r1} read_sector_loop: - @ all the functions called in this loop don't change the value of r0 or r1 + @ all the functions called in this loop don't change the value of any register @ except sclite_readData, which will increase r0 by 512 automatically CALL sclite_readData readInterwork @@ -226,14 +253,15 @@ read_sector_loop: bne read_sector_loop @ STOP_TRANSMISSION + @ puts the value in r2 SD_COMMAND_ARGUMENT #12 @ 2nd parameter is passed in r1 @ and from the loop above r1 is already 0 - + LOAD_INTERWORK_FUNCTION sccmn_sdSendClock10 readInterwork r6 CALL sclite_sdCommandAndDropResponse6 readInterwork - @ this function will trash r4 but leave r0 and r1 untouched - CALL sccmn_sdSendClock10 readInterwork + @ this function won't touch anything + @ CALL sccmn_sdSendClock10 readInterwork movs r0, #1 @@ -312,15 +340,17 @@ sclite_readData_loop: .section "sclite_write_data", "ax" @ void sclite_writeData(void*& buffer, int value_to_keep, int crc_buff1, int crc_buff2) -@ this function updates r0, leaves r1 untouched and thrashes r4 +@ this function updates r0 and leaves everything else untouched +@ in r6 is the pointer to sccmn_sdSendClock10 BEGIN_THUMB_FUNCTION sclite_writeData + @ push sccmn_sdSendClock10 and the current lr reg to the stack, so that at the end we can + @ call in sequence sccmn_sdSendClock10 and then return + push {r6} + push {r1-r7} @ loads sd_dataadd movs r4, #0x90 lsls r4, r4, #20 - @ save sd_dataadd constant above for later - push {r1-r7,lr} - waitOnWriteFalse_WriteData: ldrh r1, [r4] lsrs r1, #9 @@ -356,9 +386,12 @@ sclite_writeData_loop: @ r1 holds a value that has not to be changed @ r2-r3 hold the crc value to be written - @ r4 holds the value sd_dataadd saved at the start - pop {r1-r4} + pop {r1-r3} + stmia r7!, {r2-r3} + @ loads sd_dataadd + movs r4, #0x90 + lsls r4, r4, #20 @ write end bit movs r3, #0xff @@ -374,7 +407,11 @@ waitOnWriteTrue_WriteData: str r3, [r4] str r3, [r4] - pop {r5-r7,pc} + + @ we pop from the stack r6 as pc, which corresponds to sccmn_sdSendClock10 so we jump to it + @ sccmn_sdSendClock10 doesn't push a new lr but pops a preexisting one from the stack, which in our case is the + @ lr provided to this function + pop {r4-r7,pc} .balign 4 .pool diff --git a/arm9/source/patches/platform/supercard/scsd/SuperCardSDImpl.h b/arm9/source/patches/platform/supercard/scsd/SuperCardSDImpl.h index 3593abf..66dd438 100644 --- a/arm9/source/patches/platform/supercard/scsd/SuperCardSDImpl.h +++ b/arm9/source/patches/platform/supercard/scsd/SuperCardSDImpl.h @@ -81,7 +81,7 @@ public: { INTERWORK_LABEL(scsd_writeData, writeInterwork) = (u32)superCardWriteDataPatchCode->GetWriteDataFunction(); INTERWORK_LABEL(sccmn_sdio4BitCrc16, writeInterwork) = (u32)superCardCommonPatchCode->GetCrc16ChecksumFunction(); - INTERWORK_LABEL(sccmn_sdSendClock10, writeInterwork) = (u32)superCardCommonPatchCode->GetSdSendClock10Function(); + INTERWORK_LABEL(sccmn_sdSendClock10, writeInterwork) = (u32)superCardChangeModePatchCode->GetSdSendClock10Function(); INTERWORK_LABEL(sccmn_changeMode, writeInterwork) = (u32)superCardChangeModePatchCode->GetScChangeModeFunction(); INTERWORK_LABEL(scsd_sdCommandAndDropResponse6, writeInterwork) = (u32)superCardSdCommandAndDropPatchCode->GetSdCommandAndDropResponse6Function(); @@ -107,7 +107,7 @@ public: INTERWORK_LABEL(scsd_sdCommandAndDropResponse6, readInterwork) = (u32)superCardSdCommandAndDropPatchCode->GetSdCommandAndDropResponse6Function(); INTERWORK_LABEL(scsd_readData, readInterwork) = (u32)superCardReadDataPatchCode->GetReadDataFunction(); - INTERWORK_LABEL(sccmn_sdSendClock10, readInterwork) = (u32)superCardCommonPatchCode->GetSdSendClock10Function(); + INTERWORK_LABEL(sccmn_sdSendClock10, readInterwork) = (u32)superCardChangeModePatchCode->GetSdSendClock10Function(); } const ReadSectorsFunc GetReadSectorsFunction() const override diff --git a/arm9/source/patches/platform/supercard/scsd/SuperCardSDImpl.s b/arm9/source/patches/platform/supercard/scsd/SuperCardSDImpl.s index 9e7b143..39fab65 100644 --- a/arm9/source/patches/platform/supercard/scsd/SuperCardSDImpl.s +++ b/arm9/source/patches/platform/supercard/scsd/SuperCardSDImpl.s @@ -23,9 +23,9 @@ .macro LOAD_FAST_EXMEMCNT @ loads EXMEMCNT register address - movs r6, #0x18 + movs r0, #0x18 @ waitstate 2,1 and arm9 slot2 access - strb r6, [r7, #4] + strb r0, [r7, #4] .endm .macro RESTORE_EXMEMCNT @@ -43,11 +43,18 @@ @ void scsd_sdCommandAndDropResponse6(uint32_t dummy, uint32_t argument, SD_COMMANDS command) @ argument is passed in r1 BEGIN_THUMB_FUNCTION scsd_sdCommandAndDropResponse6 + push {lr} + cmp r2, #0x52 + @ if command is READ_MULTIPLE_BLOCK, don't send extra clock cycles + beq 1f + @ we need to call sccmn_sdSendClock10 after the command is sent, push sccmn_sdSendClock10 and the lr to the stack + push {r6} +1: @ among the pushed registers there are the command and @ argument one, which are then used by the crc7 function @ and in the loop at the bottom @ also allocate an extra 4 bytes for the SD_CRC7 function to put the crc byte - push {r0-r7,lr} + push {r0-r7} @ pass the buffer incremented by 4, so that the crc function @ can use a proper indexing method @@ -99,7 +106,9 @@ SDCommand_drop_resp: subs r6, r6, #1 bne SDCommand_drop_resp - @ restore stack space + @ we pop from the stack r6 as pc, which corresponds to sccmn_sdSendClock10 or lr, if it is sccmn_sdSendClock10 that function + @ is called, and that function doesn't push a new lr but pops a preexisting one from the stack, which in our case is the + @ lr provided to this function pop {r0-r7,pc} @ inline uint8_t CRC7_one(uint8_t crcIn, uint8_t data) { @@ -169,7 +178,7 @@ skip_xor: BEGIN_THUMB_FUNCTION scsd_writeSector push {r1,r2,r4-r7,lr} - @ load EXMEMCNT register + @ load EXMEMCNT register into r7 LOAD_SLOW_EXMEMCNT @ r1 for now holds the sector @@ -179,23 +188,34 @@ scsd_writeSectorSdhcLabel: lsls r1, r0, #9 @ movs r1, r0 + @ r4 sccmn_changeMode + @ r5 scsd_sdCommandAndDropResponse6 + @ r6 sccmn_sdSendClock10 + + adr r3, sccmn_changeMode_writeInterwork_address + ldmia r3!, {r4-r6} + @ enable sd access - @ this function won't touch r1 + @ this function won't touch anything movs r0, #3 - bl scsd_sccmn_changeMode_call + @ call sccmn_changeMode + bl interwork_r4 @ WRITE_MULTIPLE_BLOCK SD_COMMAND_ARGUMENT #25 @ 2nd parameter is in r1 from above - bl scsd_sdCommandAndDropResponse6_call - - @ this function will trash r4 but leave r0 and r1 untouched - bl scsd_sccmn_sdSendClock10_call + @ call scsd_sdCommandAndDropResponse6 + bl interwork_r5 LOAD_FAST_EXMEMCNT - @ loads the saved r0 and r2 (readnum) + @ load the rest of the functions + @ r4 sccmn_sdio4BitCrc16 + @ r5 scsd_writeData + ldmia r3!, {r4-r5} + + @ loads the saved r1 (buff) and r2 (writenum) @ into r0 and r1 pop {r0,r1} @@ -203,18 +223,17 @@ write_sector_loop: @ all the functions called in this loop don't change the value of r0 and r1 @ except scsd_writeData, which will increase r0 by 512 @ sccmn_sdio4BitCrc16 will write the checksum to r2-r3 - CALL sccmn_sdio4BitCrc16 writeInterwork - - @ first argument is buffer - @ regs r2 and r3 hold the crc - CALL scsd_writeData writeInterwork - - @ this function will trash r4 but leave r0 and r1 untouched - bl scsd_sccmn_sdSendClock10_call + @ call sccmn_sdio4BitCrc16, this function will then tail call to r5 (scsd_writeData) + bl interwork_r4 subs r1, #1 bne write_sector_loop + adr r3, sccmn_changeMode_writeInterwork_address + @ r4 sccmn_changeMode + @ r5 scsd_sdCommandAndDropResponse6 + ldmia r3!, {r4-r5} + RELOAD_SLOW_EXMEMCNT @ STOP_TRANSMISSION @@ -222,39 +241,38 @@ write_sector_loop: @ 2nd parameter is passed in r1 @ and from the loop above r1 is already 0 - bl scsd_sdCommandAndDropResponse6_call + @ call scsd_sdCommandAndDropResponse6 + bl interwork_r5 - @ this function will trash r4 but leave r0 and r1 untouched - bl scsd_sccmn_sdSendClock10_call + @ loads sd_dataadd + movs r0, #0x90 + lsls r0, r0, #20 - @ SD_DATAADD is loaded by scsd_writeData into r5 - @ while(*r5 &0x100) == 0 + @ while(*r0 &0x100) == 0 beginwhile_WriteSector: - ldrh r1, [r5] + ldrh r1, [r0] lsrs r1, #9 bcc beginwhile_WriteSector movs r0, #1 - bl scsd_sccmn_changeMode_call + @ call sccmn_changeMode writeInterwork + bl interwork_r4 @ restore EXMEMCNT register RESTORE_EXMEMCNT pop {r4-r7,pc} -scsd_sccmn_sdSendClock10_call: - LOAD_INTERWORK_FUNCTION sccmn_sdSendClock10 writeInterwork r4 +interwork_r4: bx r4 -scsd_sdCommandAndDropResponse6_call: - LOAD_INTERWORK_FUNCTION scsd_sdCommandAndDropResponse6 writeInterwork r4 - bx r4 -scsd_sccmn_changeMode_call: - LOAD_INTERWORK_FUNCTION sccmn_changeMode writeInterwork r4 -INTERWORK writeInterwork -INTERWORK_FUNCTION scsd_writeData writeInterwork -INTERWORK_FUNCTION sccmn_sdio4BitCrc16 writeInterwork -INTERWORK_FUNCTION sccmn_sdSendClock10 writeInterwork +interwork_r5: + bx r5 +.balign 4 +.pool INTERWORK_FUNCTION sccmn_changeMode writeInterwork INTERWORK_FUNCTION scsd_sdCommandAndDropResponse6 writeInterwork +INTERWORK_FUNCTION sccmn_sdSendClock10 writeInterwork +INTERWORK_FUNCTION sccmn_sdio4BitCrc16 writeInterwork +INTERWORK_FUNCTION scsd_writeData writeInterwork .section "scsd_read_sector", "ax" @@ -283,7 +301,7 @@ scsd_readSectorSdhcLabel: LOAD_FAST_EXMEMCNT - @ loads the saved r0 and r2 (writenum) + @ loads the saved r1 (buff) and r2 (readnum) @ into r0 and r1 pop {r0,r1} read_sector_loop: @@ -300,13 +318,9 @@ read_sector_loop: SD_COMMAND_ARGUMENT #12 @ 2nd parameter is passed in r1 @ and from the loop above r1 is already 0 - + LOAD_INTERWORK_FUNCTION sccmn_sdSendClock10 readInterwork r6 CALL scsd_sdCommandAndDropResponse6 readInterwork - @ this function will trash r4 but leave r0 and r1 untouched - CALL sccmn_sdSendClock10 readInterwork - - movs r0, #1 CALL sccmn_changeMode readInterwork @@ -357,14 +371,15 @@ write32_loop: @ void scsd_writeData(void* buffer, int value_to_keep, int crc_buff1, int crc_buff2) BEGIN_THUMB_FUNCTION scsd_writeData + @ push sccmn_sdSendClock10 and the current lr reg to the stack, so that at the end we can + @ call in sequence sccmn_sdSendClock10 and then return + push {r6} + push {r1-r7} - @ loads SD_DATAADD, do it before the push so that - @ it becomes available to the callee afterwards + @ loads SD_DATAADD movs r5, #0x90 lsls r5, r5, #20 - push {r1-r7,lr} - @ while(*r5 &0x100) == 0 scsd_writeData_waitOnWriteFalse: ldrh r6, [r5] @@ -384,6 +399,7 @@ scsd_writeData_waitOnWriteFalse: lsls r1, r1, #2 @ no need for special handling because those 2 functions will be in the same block bl SCSD_writeBuffer32 + @ save incremented r0 register push {r0} movs r1, #8 @@ -403,6 +419,11 @@ scsd_writeData_waitOnWriteTrue: lsrs r6, #9 bcs scsd_writeData_waitOnWriteTrue + + @ we pop from the stack r6 as pc, which corresponds to sccmn_sdSendClock10 so we jump to it + @ sccmn_sdSendClock10 doesn't push a new lr but pops a preexisting one from the stack, which in our case is the + @ lr provided to this function + @ also we load in r0 the value stored above pop {r0-r7,pc} .balign 4