====== CPU ====== Центральным процессором PlayStation является MIPS R3000, 32-битный RISC-микропроцессор, реализующий ISA MIPS I. ===== Регистры ===== R3000 имеет 32 регистра общего назначения: * $0 - r0 - всегда равен нулю * $1 - at - временные данные для некоторых псевдоинструкций ассемблера * $2..$3 - v0..v1 - возвратные значения процедур * $4..$7 - a0..a3 - аргументы процедур * $8..$15 - t0..t7 - переменные * $16..$23 - s0..s7 - статические переменные процедур * $24..$25 - t8..t9 - переменные * $26..$27 - k0..k1 - зарезервированы для [[BIOS]] * $28 - gp - [[global_pointer|глобальный указатель]] * $29 - sp - [[stack_pointer|стековый указатель]]. Содержит первый свободный адрес на стеке * $30 - fp/s8 - [[frame_pointer|указатель на фрейм]] * $31 - ra - [[return_address|адрес возврата]]. Переход по этому адресу осуществляет возврат из процедуры. Особые регистры: * hi, lo - результат целочисленного умножения/деления (верхняя и нижнняя части) * pc - программный счетчик. O32 ABI: * $2..$3 (v0..v1) - возвратные значения * $4..$7 (a0..a3) - аргументы * $29 - указатель на стек * $31 - адрес возврата. Если функция использует более 4 32-битных аргументов, 5-й аргумент и далее кладутся на стек. ===== Инструкции ===== **Арифметика:** * add $r, $a, $b - сложение. $r = $a + $b * addu $r, $a, $b - беззнаковое сложение. $r = $a + $b * addi $r, $a, imm - сложение с константой. $r = $a + imm * addiu $r, $a, imm - беззнаковое сложение с константой. $r = $a + imm * sub $r, $a, $b - вычитание. $r = $a - $b * subu $r, $a, $b - беззнаковое вычитание. $r = $a - $b * mult $a, $b - умножение. $a * $b * multu $a, $b - беззнаковое умножение. $a * $b * div $a, $b - деление. $a / $b * divu $a, $b - беззнаковое деление. $a / $b **Сравнение:** * slt $r, $a, $b - проверка условия "меньше". $r = (int)$a < (int)$b * slti $r, $a, imm - проверка условия "меньше" с константой. $r = (int)$a < imm * sltiu $r, $a, imm - беззнаковая проверка условия "меньше" с константой. $r = $a < imm **Побитовые операции:** * and $r, $a, $b - побитовое "И". $r = $a & $b * andi $r, $a, imm - побитовое "И" с константой. $r = $a & imm * or $r, $a, $b - побитовое "ИЛИ". $r = $a | $b * ori $r, $a, imm - побитовое "ИЛИ" с константой. $r = $a | imm * xor $r, $a, $b - исключающее "ИЛИ". $r = $a ^ $b * nor $r, $a, $b - отрицающее "ИЛИ". $r = !($a | $b) * sll $r, $a, imm - логический сдвиг влево на константное значение. $r = $a << imm * sllv $r, $a, $b - логический сдвиг влево на переменное значение. Значение сдвига маскируется на 5 бит. $r = $a << ($b & 0x1f) * slr $r, $a, imm - логический сдвиг вправо на константное значение. Верхние биты результата заполняются нулями. $r = $a >> imm * srlv $r, $a, $b - логический сдвиг вправо на переменное значение. Верхние биты результата заполняются нулями. Значение сдвига маскируется на 5 бит. $r = $a >> ($b & 0x1f) * sra $r, $a, imm - арифметический сдвиг вправо на константное значение. Верхние биты результата заполняются битом знака входного значения. $r = (int)$a >> imm * srav $r, $a, $b - арифметический сдвиг вправо на переменное значение. Верхние биты результата заполняются битом знака входного значения. Значение сдвига маскируется на 5 бит. $r = (int)$a >> ($b & 0x1f) **Чтение и запись памяти:** **Внимание!** Инструкции доступа к оперативной памяти требуют выровненные адреса. Доступ к слову (word) требует выравнивание по 4 байта, доступ к полуслову (half-word) требует выравнивание по 2 байта. Использование невыровненных адресов приведет к исключению шины. * lw $r, imm($a) - загружает слово. $r = $a + imm * lh $r, imm($a) - загружает полуслово. $r = $a + imm * lhu $r, imm($a) - загружает беззнаковое полуслово. $r = $a + imm * lb $r, imm($a) - загружает байт. $r = $a + imm * lbu $r, imm($a) - загружает беззнаковый байт. $r = $a + imm * lwl $r, imm($a) - загружает старшие байты слова по невыровненному адресу * lwr $r, imm($a) - загружает младшие байты слова по невыровненному адресу * sw $r, imm($a) - сохраняет слово. $a + imm = $r * sh $r, imm($a) - сохраняет полуслово. $a + imm = $r * sb $r, imm($a) - сохраняет байт. $a + imm = $r * lui $r, imm` - загружает константу в старшие 16 бит слова Инструкции загрузки не останавливают исполнение программы до тех пор, пока данные не будут доступны. Поэтому, если следующая инструкция зависит от загруженных данных, необходимо вставить [[слот задержки]]. **Безусловный переход:** * j imm - безусловный переход по константному адресу * jr $r - безусловный переход по переменному адресу * jal imm - безусловный переход по константному адресу с сохранением адреса возврата в $31 * jalr $r - безусловный переход по переменному адресу с сохранением адреса возврата в $31 * jalr $r, $a - двухадресная форма jalr. Позволяет задать регистр для сохранения адреса возврата **Условный переход (ветвление):** * beq $r, $a, imm - переход по константному адресу при равенстве операндов * bne $r, $a, imm - переход по константному адресу при неравенстве операндов * bgez $r, imm - переход по константному адресу, если операнд больше или равен нулю * bltz $r, imm - переход по константному адресу, если операнд меньше нуля * bgezal $r, imm - переход по константному адресу, если операнд больше или равен нулю, с сохранением адреса возврата в $31 * bltzal $r, imm - переход по константному адресу, если операнд меньше нуля, с сохранением адреса возврата в $31 **Псевдоинструкции:** * li $r, imm - загружает 32-битную константу. Если значение длиннее 16 бит, инструкция транслируется в lui и ori. Если значение умещается в 16 бит и не имеет знака, транслируется в ori. Если значение умещается в 16 бит и имеет знак, транслируется в addiu с нулевым первым операндом * nop - то же самое, что sll $0, $0, 0 (такой вариант удобен тем, что в машинном коде выглядит как 0x00000000). Инструкция-филлер, известная также как "слот задержки".