From fd0b828d9a4d341830190e56c5153eea6c10f55b Mon Sep 17 00:00:00 2001 From: megazig Date: Tue, 9 Apr 2013 16:21:26 -0500 Subject: fixed codehandler to work with dynamic relocation. also fixed tx checking in the usbgecko handling code --- codehandler.yaml | 4 +- src/codehandler.S | 878 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 880 insertions(+), 2 deletions(-) create mode 100755 src/codehandler.S diff --git a/codehandler.yaml b/codehandler.yaml index cfbeb9e..377d80b 100644 --- a/codehandler.yaml +++ b/codehandler.yaml @@ -1,8 +1,8 @@ -source_files: [../src/codehandler.o] +source_files: [../src/codehandler.S] hooks: - name: CodeHandlerHook type: branch_insn branch_type: b src_addr_pal: 0x801bdf78 - target_func: '_start' + target_func: '_codehandler_start' diff --git a/src/codehandler.S b/src/codehandler.S new file mode 100755 index 0000000..da62466 --- /dev/null +++ b/src/codehandler.S @@ -0,0 +1,878 @@ +# initial setup +# * add exception handling for all cases +# many breakpoints handling +# * add breakpoint list with addresses +# * add breakpoint list with original values +# allow PPC side searches +# * u32 with number of matches +# * list of addresses that match +# breakpoint conditions +# * address == foo +# * && +# * r* == bar +# * r* != bar +# * r* > bar +# * r* < bar + +.text + +#if 0 +.set r0,0; .set r1,1; .set r2,2; .set r3,3; .set r4,4 +.set r5,5; .set r6,6; .set r7,7; .set r8,8; .set r9,9 +.set r10,10; .set r11,11; .set r12,12; .set r13,13; .set r14,14 +.set r15,15; .set r16,16; .set r17,17; .set r18,18; .set r19,19 +.set r20,20; .set r21,21; .set r22,22; .set r23,23; .set r24,24 +.set r25,25; .set r26,26; .set r27,27; .set r28,28; .set r29,29 +.set r30,30; .set r31,31; .set f0,0; .set f2,2; .set f3,3 +#endif + +.set FROZENVAL, 18; +.set CCOO, 20; +.set ZEROVAL, 21; +.set CRCHECK, 22; +.set EXIPORT, 23; +.set CDOO, 24; +.set MSR, 25; +.set NEWMSR, 26; +.set REMAINDER, 27; +.set MP3PROT, 28; +.set RECVBYTE, 29; +.set TEMPLR, 30; +.set STATE, 31; + +.globl _codehandler_start + +gameid: +.long 0,0 +cheatdata: +.long frozenvalue +.space 39*4 + +.extern OSReport +_codehandler_start: +#if 0 + lis r3, debug_string@h + ori r3, r3, debug_string@l + bl OSReport +debug_string: +.string "Codehandler called\n" +#endif + stwu r1,-168(r1) # stores sp + stw r0,8(r1) # stores r0 + + mflr r0 + stw r0,172(r1) # stores lr + + mfcr r0 + stw r0,12(r1) # stores cr + + mfctr r0 + stw r0,16(r1) # stores ctr + + mfxer r0 + stw r0,20(r1) # stores xer + + stmw r3,24(r1) # saves r3-r31 + + mfmsr MSR + ori NEWMSR,MSR,0x2000 #enable floating point ? + andi. NEWMSR,NEWMSR,0xF9FF + mtmsr NEWMSR + + stfd f2,152(r1) # stores f2 + stfd f3,160(r1) # stores f3 + + lis CCOO, 0xCC00 + lhz MP3PROT, 0x4010(CCOO) + ori r21, MP3PROT, 0xFF + sth r21, 0x4010(CCOO) # disable MP3 memory protection + +_check_state: + lis STATE, state@h + ori STATE, STATE, state@l + lwz r5, 0(STATE) + cmpwi r5, 0 + bne- _setvalues + +_init_exceptions: + # 4,3,5,17 are trampled + lis r4,bphandler@h + ori r4,r4,bphandler@l + lis r3,0x8000 + ori r3,r3,0x300 # bprw 0x80000300 + bl writebranch + + addi r3,r3,0xA00 # trace 0x80000D00 + bl writebranch + + addi r3,r3,0x600 # bpx 0x80001300 + bl writebranch + + li r5, 1 + stw r5, 0(STATE) # set state to 1 (exception handling linked) + +_setvalues: + li ZEROVAL,0 + li CRCHECK,0x19 + li EXIPORT,0xD0 + lis CDOO,0xCD00 + + lis FROZENVAL, frozenvalue@h + ori FROZENVAL, FROZENVAL, frozenvalue@l # read buffer just store in lowmem + lwz r0,172(r1) # loads lr + #stw r0,4(r18) # stores lr + stw r0,4(FROZENVAL) # stores lr + stw ZEROVAL, 0x643C(CDOO) # exi speed up + +frozen: + bl exireceivebyte + beq finish # r3 returns 1 or 0, one for byte received ok + +checkcommand: + cmpwi RECVBYTE, 0x04 # checks if 8/16/32 bits write command + bge _nextcommand + cmpwi RECVBYTE, 0x01 + blt finish + b writedword #write value to address +_nextcommand: + beq readmem + cmpwi RECVBYTE, 0x06 + beq freezegame + cmpwi RECVBYTE, 0x07 + beq unfreezegame + cmpwi RECVBYTE, 0x08 + beq resumegame + cmpwi RECVBYTE, 0x09 + beq breakpoints #ibp + cmpwi RECVBYTE, 0x10 + beq breakpoints #dbp + cmpwi RECVBYTE, 0x2F + beq upbpdata + cmpwi RECVBYTE, 0x30 + beq getbpdata + cmpwi RECVBYTE, 0x38 + beq cancelbreakpoints + cmpwi RECVBYTE, 0x41 + beq uploadcode + cmpwi RECVBYTE, 0x44 + beq breakpoints #step + cmpwi RECVBYTE, 0x50 + beq pausestatus + cmpwi RECVBYTE, 0x89 + beq breakpoints #aligned dbp + cmpwi RECVBYTE, 0x99 + beq versionnumber + b finish + +#****************************************************************** +# subroutine: getpausestatus: +# zero running, one paused, two on a breakpoint +#****************************************************************** + +pausestatus: + lwz r3,0(FROZENVAL) + bl exisendbyte + b finish + + +#****************************************************************** +# subroutine: freezegame: +# Write a 1 to a memory location to freeze +#****************************************************************** + +freezegame: + li r4, 1 + stw r4, 0(FROZENVAL) + b finish + +#****************************************************************** +# subroutine: unfreezegame: +# Write a 0 to a memory location to unfreeze +#****************************************************************** + +unfreezegame: + stw ZEROVAL, 0(FROZENVAL) + b resumegame + +#****************************************************************** +# subroutine: upload bp data: +# receive the dp databuffer from the PC +#****************************************************************** + +upbpdata: + bl exisendbyteAA + + li r16, 40*4 # 40 "registers rN" * 4 + lis r12, regbuffer@h + ori r12, r12, regbuffer@l + b upload + +#****************************************************************** +# subroutine: getbp data: +# send the dp databuffer to the PC +#****************************************************************** + +getbpdata: + li r3, 72*4 # register buffer + lis r12, regbuffer@h + ori r12, r12, regbuffer@l + bl exisendbuffer # send it, less than a packet + b finish + + +#****************************************************************** +# subroutine: breakpoints: +# handles data/instruction address breakpoints +#****************************************************************** + +breakpoints: + + cmpwi cr6,RECVBYTE,0x10 # 0x10=instruction, 0x09/0x89=data + cmpwi cr5,RECVBYTE,0x44 # 0x44=step + + lis r4, bphandler@h + ori r4,r4,bphandler@l #used for writebranch (=source address) + + lis r3,0x8000 + ori r3,r3,0x300 # bprw 0x80000300 + bl writebranch + + addi r3,r3,0xA00 # trace 0x80000D00 + bl writebranch + + addi r3,r3,0x600 # bpx 0x80001300 + bl writebranch + + lis r12, bpbuffer@h + ori r12, r12, bpbuffer@l # read buffer just store in lowmem + + stw ZEROVAL,0(r12) # clears inst bp + stw ZEROVAL,4(r12) # clears data bp + stw ZEROVAL,8(r12) # clears alignement + + lis r4, regbuffer@h + ori r4, r4, regbuffer@l + lwz r9,0x18(r4) # srr1 + + lwz r3,0(FROZENVAL) + cmpwi r3,2 # checks if the gecko is on a breakpoint + ;bne +12 + ;beq cr5,+12 + bne p12 + beq cr5, p12_2 + b bp +p12: + li r3,0 +p12_2: + stw r3,12(r12) # if not, clears the previous "broken on" address + bne bp + + bne cr5,bp + ori r9,r9,0x400 + stw r9,0x18(r4) # srr1 |= 0x400 # set SE (single step) + b unfreezegame + +bp: + rlwinm r9,r9,0,22,20 + stw r9,0x18(r4) # srr1 &= 0xfffffbff # clear SE (single step) + beq cr5,finish + ;beq cr6,+8 + beq cr6, p8 + addi r12,r12,4 # if databp r12=r12+4 + +p8: + li r3, 4 # 4 bytes + bl exireceivebuffer + + ble cr6,noalignement # if not aligned data bp (0x89) + + addi r12,r12,4 + + li r3, 4 # 4 bytes + bl exireceivebuffer + +noalignement: + lis r4, bpbuffer@h + ori r4, r4, bpbuffer@l # read buffer just store in lowmem + + lwz r3, 0(r4) # inst bp + lwz r4, 4(r4) # data bp + mtspr 1010, r3 # set IABR + mtspr 1013, r4 # set DABR + b finish + +#****************************************************************** +# subroutine: bphandler +# Data/Instruction address breakpoint handler, save context and return +#****************************************************************** + +#FIXME +bphandler: + mtsprg 2,r1 # sprg2 = r1 + lis r1, regbuffer@h + ori r1, r1, regbuffer@l + mtsprg 3,r3 # sprg3 = r3 + mfsrr1 r3 # r3=srr1 + rlwinm r3,r3,0,22,20 # clear trace + xoris r1, r1, 0x8000 # ensure physical address + stw r3, 0x18(r1) + rlwinm r3,r3,0,24,15 + ori r3,r3,0x2000 + mfsrr0 r1 # r1=srr0 + +# rlwinm r3,r3,0,17,15 # clear hw interrupt + mtsrr1 r3 # restore srr1 with hw interrupt & trace cleared + + lis r3,break@h + ori r3,r3,break@l + mtsrr0 r3 + rfi + +break: + lis r3, regbuffer@h + ori r3, r3, regbuffer@l + stw r1,0x14(r3) #stores srr0 + + mr r1,r3 + mfsprg r3,3 + stmw r2,0x24(r1) #saves r2-r31 + mr r4,r1 + mfsprg r1,2 + + stw r0,0x1C(r4) + stw r1,0x20(r4) + + mflr r3 + stw r3, 0x9C(r4) # Store LR + + mfcr r3 + stw r3, 0x0(r4) # Store CR + + mfxer r3 + stw r3, 0x4(r4) # Store XER + + mfctr r3 + stw r3, 0x8(r4) # Store CTR + + mfdsisr r3 + stw r3, 0xC(r4) # Store DSISR + + mfdar r3 + stw r3, 0x10(r4) # Store DAR + + li r9,0 + mtspr 1010,r9 # Clear IABR + mtspr 1013,r9 # Clear DABR + + lis r5,floatstore@h + ori r5,r5,floatstore@l # Set r5 to instruction address + lis r31,0xD004 + ori r31,r31,0x00A0 # Set r31 to 'stfs f0,0xA0(r4)' (==0xD00400A0) +floatloop: + stw r31,0(r5) + dcbst r0,r5 + sync + icbi r0,r5 + isync +floatstore: + stfs f0,0xA0(r4) + addi r31,r31,4 # Advance instruction offset + addis r31,r31,0x20 # Advance instruction register + rlwinm. r16,r31,0,5,5 # Check for register > 31 + beq floatloop + +skip_floating_point: + + lis r5, bpbuffer@h + ori r5,r5,bpbuffer@l + + lwz r16,0(r5) # inst bp + lwz r17,4(r5) # data bp + lwz r19,12(r5) # counter for alignment + + cmpwi r19,0 + beq _redobp + + cmpwi r19,2 + ;bne +24 + bne p24 + lwz r9,0x14(r4) + addi r9,r19,3 + stw r9,0(r5) # inst bp + stw r9,12(r5) # counter for alignment + b _executebp + +p24: + cmpw r16,r19 + beq _step + + cmpw r17,r19 + beq _step + + add r9,r16,r17 + stw r9,12(r5) # counter for alignment + + +_alignementcheck: + lwz r16,8(r5) # bp alignment check + cmpwi r16,0 + beq _executebp # no alignement = normal break + + lwz r3,0x10(r4) + cmpw r16,r3 # we check if address = aligned address + bne _step # if no, we need to set a bp on the next instruction + + li r16,0 + stw r16,8(r5) # if we are on the good address we clear the aligned bp check + b _executebp # and we break + +_step: + li r17,0 + stw r17,12(r5) # counter for alignment + lwz r9,0x18(r4) + ori r9,r9,0x400 + stw r9,0x18(r4) + b _skipbp #and we don't break right now + +_redobp: + mtspr 1010,r16 # we set back the instbp with the original value + mtspr 1013,r17 # we set back the databp with the original value + li r9,1 + stw r9,12(r5) # counter for alignment + b _skipbp # and we don't break + +_executebp: + li r5, 2 + ;TODO check FROZENVAL vs r4 in other + lis FROZENVAL, frozenvalue@h + ori FROZENVAL, FROZENVAL, frozenvalue@l # Freeze once returned to let user know there is a breakpoint hit + stw r5, 0(FROZENVAL) + +# NOT NEEDED BY MEGAZIG +# li r3, 0x11 +# bl exisendbyte # tell the PC a bp has happened (send 0x11) +# + nop + nop + + bl _codehandler_start # bl mainloop, so you can set up a new breakpoint. + +_skipbp: + mfmsr r1 + rlwinm r1,r1,0,31,29 + rlwinm r1,r1,0,17,15 + mtmsr r1 # we disable the interrupt so nothing interfers with the restore + + lis r1, regbuffer@h + ori r1, r1, regbuffer@l + + lwz r3,0x0(r1) + mtcr r3 # restores CR + lwz r3,0x14(r1) + mtsrr0 r3 # restores SRR0 + lwz r3,0x18(r1) + mtsrr1 r3 # restores SRR1 + lwz r3,0x9C(r1) + mtlr r3 # restores LR + + lmw r2,0x24(r1) # restores r2-r31 + + lwz r0,0x1C(r1) # restores r0 + lwz r1,0x20(r1) # restores r1 + + rfi # back to the game + +#****************************************************************** +# subroutine: write dword: +# Write a long word value to memory sent from PC +#****************************************************************** + +writedword: + cmpwi cr5,RECVBYTE,2 + li r3, 8 # 8 bytes (location 4 / Value 4) + + lis r12, dwordbuffer@h + ori r12, r12, dwordbuffer@l # buffer + bl exireceivebuffer + + lwz r5, 0(r12) + lwz r3, 4(r12) # read the value + stb r3, 0(r5) # write to location + blt cr5,skipp + sth r3, 0(r5) # write to location + beq cr5,skipp + stw r3, 0(r5) # write to location +skipp: + dcbf r0, r5 # data cache block flush + sync + icbi r0, r5 + isync + b finish + +#****************************************************************** +# subroutine: Upload : +# Fill memory with value +#****************************************************************** + +uploadcode: + bl exisendbyteAA + + li r3, 8 # 8 bytes + lis r12, dwordbuffer@h + ori r12, r12, dwordbuffer@l # buffer + + bl exireceivebuffer + + lwz r16, 4(r12) + lwz r12, 0(r12) + +upload: + lis REMAINDER, rem@h + ori REMAINDER, REMAINDER, rem@l # Remainder of bytes upload code + li r17,0xF80 + bl _packetdivide + beq douploadremainder + +nextrecpacket: + mr r3,r17 + bl exireceivebuffer # r12 start = start of buffer + +uploadwait: + bl exisendbyteAA + beq uploadwait + add r12,r12,r14 + + subic. r11, r11, 1 # decrease loop counter + bgt nextrecpacket + +douploadremainder: # send the remainder bytes + lwz r3, 0(REMAINDER) # remainder + cmpwi r3,0 + beq finishupload + bl exireceivebuffer +finishupload: + dcbf r0, r12 # data cache block flush + sync + icbi r0, r12 # instruction cache block flush + isync + b finish + +#****************************************************************** +# subroutine: exireceivebyte: +# Return 1(r3) if byte receive, 0(r3) if no byte +# Command byte is stored at 0x800027ff +#****************************************************************** + +exireceivebyte: + mflr TEMPLR + lis r3, 0xA000 # EXI read command + + bl checkexisend + + andis. r3, r16, 0x800 + rlwinm RECVBYTE,r16,16,24,31 + mtlr TEMPLR + blr + +#****************************************************************** +# subroutine: checkexisend: +# +#****************************************************************** + +checkexisend: + + stw EXIPORT, 0x6814(CDOO) # 32mhz Port B + stw r3, 0x6824(CDOO) + stw CRCHECK, 0x6820(CDOO) # 0xCC006820 (Channel 1 Control Register) + +exicheckreceivewait: + lwz r5, 0x6820(CDOO) + andi. r5, r5, 1 + bne exicheckreceivewait # while((exi_chan1cr)&1); + + lwz r16, 0x6824(CDOO) + stw r5, 0x6814(CDOO) + + blr + +#****************************************************************** +# subroutine: exireceivebuffer: +# r3 byte counter, r12 points to buffer, r3 gets copied as gets destroyed +#****************************************************************** + +exireceivebuffer: + mflr r10 # save link register + mtctr r3 # counter + li r14,0 + +bufferloop: + bl exicheckreceive + bl exicheckreceive + bl exireceivebyte + beq bufferloop # r3 returns 1 or 0, one for byte received ok + + stbx RECVBYTE, r14,r12 # store byte into buffer + + addi r14, r14, 1 # increase buffer by 1 + bdnz bufferloop + + mtlr r10 # retore link register + blr # return to command check + +#****************************************************************** +# exisendbuffer: +# r3 byte counter, r12 points to buffer, r3 gets copied as gets destroyed +#****************************************************************** + +exisendbuffer: + mflr r10 # save link register + mtctr r3 # r3->counter + li r14,0 + +sendloop: + bl exichecktx + beq sendloop + lbzx r3, r12,r14 + bl exisendbyte + beq sendloop + + addi r14, r14, 1 # increase buffer + bdnz sendloop + mtlr r10 # restore link register + blr + +#****************************************************************** +# exisendbyte:12345678 +# r3 byte to send, returns 1 if sent, 0 if fail (!!! called by breakpoint) +#****************************************************************** +exisendbyteAA: + li r3,0xAA + +exisendbyte: # r3, send value + mflr TEMPLR + slwi r3, r3, 20 # (sendbyte<<20); + oris r3, r3, 0xB000 # 0xB0000000 | (OR) + #TODO why am I missing? + li r22,0x19 # already done in _setvals + li r23,0xD0 # already done in _setvals + lis r24,0xCD00 # already done in _setvals + + bl checkexisend + + extrwi. r3, r16, 1,5 # returns either 0 or 1, one for byte received ok + mtlr TEMPLR + blr + +#****************************************************************** +# subroutine: exicheckrecieve: +# Return 1(r3) if byte receive, 0(r3) if no byte +#****************************************************************** + +exicheckreceive: + mflr TEMPLR +exicheckreceive2: + lis r3, 0xD000 # EXI check status command + + bl checkexisend + + rlwinm. r3,r16,6,31,31 # returns either 0 or 1 for r3 + + beq exicheckreceive2 + mtlr TEMPLR + blr + +#****************************************************************** +# subroutine: exichecktx: +# Return 1 if ok to send, 0 if not +#****************************************************************** +exichecktx: + mflr r30 + lis r3, 0xC000 + ; TODO yet I'm here + li r22, 0x09 + li r23, 0xD0 + lis r24, 0xCD00 + + bl checkexisend + + extrwi. r3, r16, 1,5 # returns either 0 or 1, one for byte received ok + mtlr r30 + blr + +#****************************************************************** +# Readmem: (reads a memory range back to PC) +# r3 byte to send, returns 1 if sent, 0 if fail +#****************************************************************** + +readmem: + bl exisendbyteAA + + li r3, 8 # 8 bytes + lis r12, dwordbuffer@h + ori r12, r12, dwordbuffer@l # buffer + + bl exireceivebuffer + + lwz r5, 4(r12) + lwz r12, 0(r12) + + lis REMAINDER, rem@h + ori REMAINDER, REMAINDER, rem@l # place holder for remainder bytes + + ori r17, ZEROVAL, 0xF800 # 64K packet + sub r16, r5, r12 # memrange = (*endlocation - *startlocation) + + bl _packetdivide + +nextsendpacket: + bgt transfer #compares r11 and 0 + lwz r17, 0(REMAINDER) # remainder + cmpwi r17,0 + beq finish +transfer: + mr r3,r17 # number of bytes + bl exisendbuffer + +bytewait1: + bl exicheckreceive + bl exicheckreceive + bl exireceivebyte + beq bytewait1 # r3 returns 1 or 0, one for byte received ok + cmpwi RECVBYTE, 0xCC # cancel code + beq finish + cmpwi RECVBYTE, 0xBB # retry code + beq transfer + cmpwi RECVBYTE, 0xAA + bne bytewait1 + add r12,r12,r14 + subic. r11, r11, 1 # decrease loop counter + blt finish + b nextsendpacket + +#****************************************************************** +# Cancel Breakpoints +# Clears instruction and data and step breakpoints +#****************************************************************** + +cancelbreakpoints: + mtspr 1013, ZEROVAL # clear the DABR + mtspr 1010, ZEROVAL # clear the IABR + lis r4, regbuffer@h + ori r4, r4, regbuffer@l + lwz r9,0x18(r4) + rlwinm r9,r9,0,22,20 + stw r9,0x18(r4) # srr1 &= ~(1<<12) # clear SE bit + b finish + +#****************************************************************** +# subroutine: version number +# Sends back the current gecko version number. +#****************************************************************** + +versionnumber: + li r3, 0x80 # 0x80 = Wii, 0x81 = NGC + bl exisendbyte + #b finish + +#****************************************************************** +# Finish +# Check if the gecko has been paused. if no return to game +#****************************************************************** + +finish: + lwz r4, 0(FROZENVAL) + cmpwi r4, 0 # check to see if we have frozen the game + bne frozen # loop around if we have + # (changed to return for the bp) + +resumegame: + + sth MP3PROT,0x4010(CCOO) # restore memory protection value + + lfd f2,152(r1) # loads f2 + lfd f3,160(r1) # loads f3 + + mtmsr MSR + + lwz r0,172(r1) + mtlr r0 # restores lr + + lwz r0,12(r1) + mtcr r0 # restores cr + + lwz r0,16(r1) + mtctr r0 # restores ctr + + lwz r0,20(r1) + mtxer r0 # restores xer + + lmw r3,24(r1) # restores r3-r31 + + lwz r0,8(r1) # loads r0 + + addi r1,r1,168 + + isync + + blr # return back to game + +#****************************************************************** +# Write branch +# r3 - source (our mastercode location) +# r4 - destination (lowmem area 0x80001800 address which will branch to +# volatile: r17, r5 +#****************************************************************** +writebranch: + + subf r17, r3, r4 # subtract r3 from r4 and place in r17 + lis r5, 0x4800 # 0x48000000 + rlwimi r5,r17,0,6,29 + stw r5, 0(r3) # result in r3 + + dcbf r0, r3 # data cache block flush + sync + icbi r0, r3 + isync + + blr # return + + + +#****************************************************************** +# Packet Divide +# Used by the down/up routines to calculate the number of packet to send +#****************************************************************** + +_packetdivide: + divw. r11, r16, r17 # fullpackets = memrange / 0xF80 (r11 is full packets) + mullw r10, r11, r17 + subf r10, r10, r16 # r10 holds remainder byte counter + stw r10, 0(REMAINDER) # store remainder + blr + +#================================================================== + +frozenvalue: #frozen value, then LR +.long 0,0 +dwordbuffer: +.long 0,0 +rem: +.long 0 +bpbuffer: +.long 0 #inst address to bp on +.long 0 #data address to bp on +.long 0 #alignement check +.long 0 #counter for alignement / previous broken on address + +regbuffer: +.space 72*4 + +state: +.long 0 # 0=none 1=linked 2=??? + +.align 4 + +codelist: +.space 2*4 +.end + -- cgit v1.2.3