Описание ассемблера для Explay m3

===============================================================
вспомогательные проги для взлома прошивки к М3 (все с исходниками)
SDK комплект разработчика для написания приложений на плеере М3

эмулятор, исполнитель прошивки на бейсике
интерпретатор прошивки
новый дизасемблер прошивки от 1 фев2007
компилятор с бейсика в машинный код

 исходники сегмента 8С000000-8С002999 (BOOT)

===============================================================
Документацию качать отсюда:
SPCA-533A.pdf	[http://mxhaard.free.fr/spca50x/Doc/Sunplus/spca533a/SPCA-533A.pdf]
vmips.pdf	[http://www.dgate.org/vmips/doc/vmips.pdf]
spim_documentation.pdf	[http://www.cs.wisc.edu/~larus/SPIM/spim_documentation.pdf]
HP_AppA.pdf	[http://www.cs.wisc.edu/~larus/HP_AppA.pdf]
psABI_mips3.0.pdf [ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/psABI_mips3.0.pdf]
MPS.user.manual.1.22.pdf [http://downloads.sourceforge.net/mps/MPS.user.manual.1.22.pdf?modtime=1079913600&big_mirror=0]

pcspim.zip - это эмулятор R3000 какой то непонятный.
www.cs.wisc.edu/~larus/SPIM/pcspim.zip [http://www.cs.wisc.edu/~larus/SPIM/pcspim.zip]

-------------------------------------------------

старый дизасемблер прошивки

преобразует в понятный язык, даже кто не знает ассемблер поймет.
половина инструкций и сопроцессор 1 не используется.
в сопроцессоре 0 используются только регистры:
Status 12 interrupt mask and enable bits
Cause  13 exception type and pending interrupt bits
EPC    14 address of instruction that caused exception
?      20 не знаю и нет описания пока
Exceptions and interrupts cause a MIPS processor 
to jump to a piece of code, at address 80000180
Есть там обработчик прерываний с переходом на 8С010800

язык мипс р3000 знать не надо, прошивка дизасемблирует
в почти язык высокого уровня, и написана в виде понятных
обозначений на Си и бейсика. осталось только понять логику
и адресацию, где память экрана, где данных, пока не ясно,
всего 243000 инструкций,  #B0000000 порты как память

генерирует примерно такой код:
8C000000 lui $sp #D001		| $sp = #D001.0000
8C000004 addiu $sp $sp #8000	| $sp = $sp + #8000
8C000008 lui $gp #8C01		| $gp = #8C01.0000
8C00000C jal #8C000180		|  
8C000010 addiu $gp $gp #A8C0	| CALL #8C000180  ; $gp = $gp + #A8C0
8C000018 lui $t3 #8C00		| $t3 = #8C00.0000
8C00001C addiu $t3 $t3 #0200	| $t3 = $t3 + #0200
8C000020 jalr $t3 $ra		|  
8C00002C lui $t4 #8C00		| CALL $t3  ; $t4 = #8C00.0000
8C000030 addiu $t4 $t4 #0450	| $t4 = $t4 + #0450
8C000034 jalr $t4 $ra		| CALL $t4 
8C000040 j #8C000040		| JMP #8C000040
....
8C00023C sw $at $v0 #1010	| ( $at + #1010 ) = $v0  запись регистра в память
....
8C000240 lw $gp $v1 #80FC	| $v1 = ( $gp + #80FC) загрузить из памяти

размещение прошивки в памяти
0000.0000 -> 8C00.0000        загрузчик
0000.4000 -> 8C01.0000        основной код

дальнейшая адресация будет дана в памяти плеера а не в прошивке.
есть таблицы адресов для переходов. много
8C0025F0-8C0028B4     первая таблица для загрузчика.

Если что то не ясно, в исходниках есть мини 
описание команд, или в HP_AppA.pdf смотреть надо что к чему.

регистры 32 разрядные 32 штуки
$zero=0, $at службный, $v0-1 для возврата значения из функций
$a0-3 аргументы, $t0-9, $s0-7, $k0-1 для ОС, $gp - сегмент данных
$sp указатель стека, $fp указатель фрейма, $ra адрес возврата.
$lo $hi -регистры для деления умножения
word=32 halword=16 byte=8      адресация индексная везде.
в знаковых инструкциях , старший бит (знак) копируется влево до 31 бита.
-----------------

Вот хорошая ссылка на дизассемблирование прошивки камеры на MIPS
http://www.maushammer.com/systems/cvscamcorder/firmware-disassembly.html
http://www.maushammer.com/systems/cvscamcorder/dismipper-0.9.zip
здесь исходники и примеры как надо искать и описывать функции в прошивке,
камера и плеер примерно одинаковы по функциям, можно по аналогии ломать,
когда будет нормальное описалово, и разобран код больше чем наполовину,
тогда можно будет улучшать код.

вот еще некоторая дока по R3000 и кое какое описание аналогичных
http://psxdev.narod.ru/docs.htm

B000.0000 это память аппаратно отображенная на устройства = порты


------------------R2000--------------------------
add   rd,rs,rt    # R[rd] = R[rs] + R[rt] 
addu  rd,rs,rt    # R[rd] = R[rs] + R[rt] 
addi  rd,rs,K     # R[rd] = R[rs] + K 
addiu rd,rs,K     # R[rd] = R[rs] + K 
sub   rd,rs,rt    # R[rd] = R[rs] - R[rt] 
subu  rd,rs,rt    # R[rd] = R[rs] - R[rt] 
mult  rs,rt       # HI = (R[rs]*R[rt])63-32  # LO = (R[rs]*R[rt])31-0 
multu rs,rt       # HI = (R[rs]*R[rt])63-32  # LO = (R[rs]*R[rt])31-0 
div   rs,rt       # HI = (R[rs]%R[rt])       # LO = (R[rs]/R[rt]) 
divu  rs,rt       # HI = (R[rs]%R[rt])       # LO = (R[rs]/R[rt]) 
slt   rd,rs,rt    # if R[rs] < R[rt]  then R[rd] = 1    #  else R[rd] = 0 
sltu   rd,rs,rt   #    -"- 
slti  rd,rs,K     # if R[rs] < K then R[rd] = 1    #  else R[rd] = 0 
sltiu rd,rs,K     #    -"- 
and   rd,rs,rt    # R[rd] = R[rs] & R[rt] 
andi  rd,rs,K     # R[rd] = R[rs] & K 
or    rd,rs,rt    # R[rd] = R[rs] | R[rt] 
ori   rd,rs,rt    # R[rd] = R[rs] | K 
nor   rd,rs,rt    # R[rd] = ~(R[rs] | R[rt]) 
xor   rd,rs,rt    # R[rd] = R[rs] ^ R[rt] 
xori  rd,rs,K     # R[rd] = R[rs] ^ K 
sll   rd,rt,K     # R[rd] = R[rt] << K 
srl   rd,rt,K     # R[rd] = R[rt] >> K 
sra   rd,rt,K     # R[rd] = R[rt] >> K 
sllv  rd,rt,rs    # R[rd] = R[rt] << R[rs] 
srlv  rd,rt,rs    # R[rd] = R[rt] >> R[rs] 
srav  rd,rt,rs    # R[rd] = R[rt] >> R[rs] 

lui   rt,K        # R[rt]31-16 = K      # R[rt]15-0 = 0 
lb    rt,diff(rs) # R[rt]7-0 = M[diff+R[rs]] # R[rt]31-8 = (M[diff+R[rs]]7)24 
lbu   rt,diff(rs) # R[rt]7-0 = M[diff+R[rs]] # R[rt]31-8 = (0)24 
lh    rt,diff(rs) # R[rt]15-0 = M.h[diff+R[rs]] # R[rt]31-16 = (M.h[diff+R[rs]]15)16 
lhu   rt,diff(rs) # R[rt]15-0 = M.h[diff+R[rs]] # R[rt]31-16 = (0)16 
lw    rt,diff(rs) # R[rt] = M.w[diff+R[rs]] 
sb    rt,diff(rs) # M[diff+R[rs]] = R[rt]7-0 
sh    rt,diff(rs) # M.h[diff+R[rs]] = R[rt]15-0 
sw    rt,diff(rs) # M.w[diff+R[rs]] = R[rt] 
mfhi  rd          # R[rd] = HI 
mflo  rd          # R[rd] = LO 
mthi  rs          # HI = R[rs] 
mtlo  rs          # LO = R[rs] 

beq   rs,rt,label # if R[rs] == R[rt] then PC = label 
bne   rs,rt,label # if R[rs] != R[rt] then PC = label 
bgez  rs,label    # if R[rs] >= 0 then PC = label 
bgtz  rs,label    # if R[rs] > 0 then PC = label 
blez  rs,label    # if R[rs] <= 0 then PC = label 
bltz  rs,label    # if R[rs] < 0 then PC = label 
j     label       # PC = label 
jr    rs          # PC = R[rs] 
jal   label       # R[31] = PC + 4   # PC = label 
jalr  rs          # R[31] = PC + 4   # PC = R[rs] 

bgezal rs,label   # temp = PC  # if R[rs] >= 0 then PC = label  # R[31] = temp+4 
bltzal rs,label   # temp = PC  # if R[rs] < 0 then PC = label   # R[31] = temp+4 
break n                    # =int N  
syscall                    # =int 21  
------------------------------------------------------

0xb0000000 - 0xb0000fff
This area holds the 128 device descriptors which describe the hardware devices
that are available in the system. For details: See Section 6.4.1 [Device descriptors],
page 29. This area is read-only, meaning that writes have no effect.
0xb0001000 - 0xb0001fff
This area holds the kernel boot parameters as a 0-terminated (C-style) string.
This area is read-only, meaning that writes have no eect.
0xb0002000 - 0xb0007fff
This area is reserved for future use. This area is read-only, meaning that writes
have no effect.
0xb0008000 - 0xbfffffff
This area holds the actual I/O ports and any additional memory areas for the
devices. Whether writing to a certain address has any eect depends on the
device and port/area in question.

OFFSET SIZE DESCRIPTION
0x00 1 word Device type code. Type code 0 is not used by any
devices, and it means that this descriptor is unused
and should be ignored. See Section 6.4.2 [Device type
codes], page 30.
0x04 1 word Device I/O address base. All I/O port osets of a device
are relative to this address.
0x08 1 word The length of the device's I/O address area in bytes.
This will always be a multiple of 4, since all ports are
32 bits wide.
0x0C 1 word The number of the IRQ that the device generates. Possible
values are from 0 to 5. A value of -1 (0xffffffff)
means the device will not generate any IRQs.
0x10 8 bytes Vendor string. These bytes are used to describe the
model of the device or some other information intended
to be read by humans. The operating system may
safely ignore the contents of these bytes. These bytes
may contain any values and need not be 0-terminated.
0x18 2 words Reserved. The contents of these word should be considered
undefened.

------------------------------------------------------
таблица для дизасемблера, вторая колонка: 32 битная маска,
третья колонка: 6 полей 6-5-5-5-5-6 бит, ??-номер регистра, ##-данные
RS RT RD регистры по порядку в 2,3,4 полях

madd                70000000      1C????000000
movz                0000000A      00??????000A
movn                0000000B      00??????000B
mfc0                40000000      1000????0000
mtc0                40800000      1004????0000
bltz                04000000      01??00######
blez                18000000      06??00######
bgtz                1C000000      07??00######
bgez                04010000      01??01######
srav                00000007      00??????0007
xor                 00000026      00??????0026
xori                38000000      0E????######
sub                 00000022      00??????0022
subu                00000023      00??????0023
div                 0000001A      00????00001A
divu                0000001B      00????00001B
mult                00000018      00????000018
multu               00000019      00????000019
sra                 00000003      0000????##03
srl                 00000002      0000????##02
srlv                00000006      00??????0006
sll                 00000000      0000????##00
sllv                00000004      00??????0004
nor                 00000027      00??????0027
or                  00000025      00??????0025
slti                28000000      0A????######
sltiu               2C000000      0B????######
slt                 0000002A      00??????002A
sltu                0000002B      00??????002B
ori                 34000000      0D????######
sh                  A4000000      29????######
sb                  A0000000      28????######
sw                  AC000000      2B????######
mthi                00000011      00??00000011
mtlo                00000013      00??00000013
mfhi                00000010      000000??0010
mflo                00000012      000000??0012
lw                  8C000000      23????######
lh                  84000000      21????######
lhu                 94000000      25????######
lb                  80000000      20????######
lbu                 90000000      24????######
lui                 3C000000      0F00??######
j                   08000000      02##########
jal                 0C000000      03##########
jalr                00000009      00??00??0009
jr                  00000008      00??00000008
bne                 14000000      05????######
beq                 10000000      04????######
andi                30000000      0C????######
and                 00000024      00??????0024
addu                00000021      00??????0021
addiu               24000000      09????######
addi                20000000      08????######
add                 00000020      00??????0020

остальные команды не используются
break #1C           0007000D непонятная команда?
ext                 7C000000      1F??????????
пока нет описания что такое, но попадается часто

документация есть на mips.com  (регистрация нужна)
http://www.mips.com/content/Documentation/MIPSDocumentation/ProcessorArchitecture/doclibrary
http://www.mips.com/content/Documentation/MIPSDocumentation/ProcessorCores/doclibrary

обнаружена существенная ошибка из-за которой не сходилась логика,
оказалось что все команды переходы имеют слот задержки - инструкция
после перехода выполняется последовательно в паре вместе с переходом
если он есть, она как бы первая в новой очереди конвеера команд.
поэтому все CALL JUMP JMP на самом деле ниже на 4 байта и относительная
адресация реально JMP +1 (+4 байта)

поэтому код:
8C00055C beq $a0 $v0 #0012      | 
8C000560 addiu $v0 0 #001D      | JMP #8C0005A4 if $a0 = $v0 ; $v0 = #001D

($v0 = #001D - выполняется сразу после перехода) 

m:000598 jr $ra                 | $sp = : 8
::00059C addiu $sp $sp #0008    | JUMP (return)  

::0006C0 jal #8C0020E4          | $a2 = #0001
::0006C4 addiu $a2 0 #0001      | CALL #8C0020E4

------------------------------------------------------------
разобранные процедуры: 
//обозначения: (p****=#B000****) (m****=#8C00****)//

c:000180| (#8C0029A8) = #8C000310 ; (#8C0029C0) = #8C000310
	| (#8C0029AC) = #8C0025F0 ; (#8C0029BC) = #8C0025F0
	| (#8C0029B0) = #8C0029A0 ; (#8C0029C4) = #8C00BF30
-------------------------------------------------------------
c:000200| byte(p1000) = 1 ; byte(p5023) = 1 //copy CODE to RAM?
	| $v1 = byte(p00B1) & 00000010 //2bit
	| (p1010) = #01A00401
	| GOTO n_240 if $v1  // 2 bit byte(p00B1)

	| $v1 = (m29A4) ; $a1 = (m29A0) ; $a0 = (m29A8) // v1<-a0..a1
	| for($v1 < $a1){($v1) = ($a0) ; $v1 += 4 ; $a0 += 4}
        | $v1 = (m29B8) ; $a1 = (m29B4) //  v2<-a1..a2 
	| for($v1 < $a1){($v1) = ($a0) ; $v1 += 4 ; $a0 += 4}

n240	| $v1 = (m29BC); $a1 = (m29B0) ; $a0 = (m29AC) // v1<-a0..a1
	| for($v1 < $a1){($v1) = ($a0) ; $v1 += 4 ; $a0 += 4}
        | $a0 = (m29C4) //a1..a2<-0 
	| if(#8C0029C8 < $a0){for($v1 < $a0 ){($v1) = 0 ; $v1 += 4}} 
-----------------------------------------------------------------
C:002574| if($a1 < 0){$a0 = -$a0; $a1 = -$a1 ; if($a0 > 0)$a1--;}
	| GOTO_CALL c002484 if $a3 >= 0
t	| $a2 = -$a2 ; $a3 = -$a3; if($a2 > 0)$a3--;
	| GOTO_CALL c002484
----------------------------------------------------------
t	| $t7 = $ra ; $t6 = $a1 ^ $a3
	| CALL 8C002574
m:0025B4| if ($t6 < 0){$v0 = -$v0 ; $v1 = -$v1 ; if($v0 > 0)$v1--;}
	| GOTO $t7     //ret
t	| $t7 = $ra ; $t6 = $a1
	| CALL 8C002574
	| $v0 = $a0 ; $v1 = $a1
	| LOOP m_0025B4
-----------------------------------------------------------------
C:001860| $sp -= 24 	; (Stek10) = $s0
	| $s0 = $a0            //a0 pointer string+chr(0)
	| GOTO n_001894 if sign_byte($s0) = 0 //end string
n:00187C| $a0 = byte($s0) ; $s0 ++
   n1840| LOOP n_1840 if byte(p1016) & 00100000 = 0 //6bit wait
	| byte(p1015) = $a0  //usb?
	| LOOP n_00187C if sign_byte($s0)
n:001894| $s0 = (Stek10) ; $sp += 24
-----------------------------------------------------------------


последнее обновление 1февраля 2007г