?> <p> ARM multiply instructions are basically plain multiplies or multiply with accumulate. They are emulated with three different instructions: INIT, IMLA, IMLB. For simplicity a multiply instruction always takes 16 cycles; early termination is not supported. INIT[CC]A Rm, Rn/0 IMLACPA Acc, Rs IMLBCPA Acc, #0 14 times IMLBCPA[S] Acc, #0 -> Rd </p> <?php arm_emulation_table_start(); arm_emulation_table_instruction("MUL[CC] Rd, Rm, Rs", "\n INIT[CC]A Rm, #0<br>\n IMLACPA Acc, Rs<br>\n IMLBCPA Acc, #0 <i>(14 times)</i><br>\n IMLBCPA[F] Acc, #0 -> Rd", "No restrictions", ""); arm_emulation_table_instruction("MLA[CC] Rd, Rm, Rs, Rn", "\n INIT[CC]A Rm, Rn<br>\n IMLACPA Acc, Rs<br>\n IMLBCPA Acc, #0 <i>(14 times)</i><br>\n IMLBCPA[F] Acc, #0 -> Rd", "No restrictions", ""); arm_emulation_table_instruction("MUL[CC]S Rd, Rm, Rs", "\n INIT[CC]A Rm, #0<br>\n IMLACPA Acc, Rs<br>\n IMLBCPA Acc, #0 <i>(14 times)</i><br>\n IMLBCPAS[F] Acc, #0 -> Rd", "No restrictions", "<em>Differs from ARM - V is corrupted</em>"); arm_emulation_table_instruction("MLA[CC]S Rd, Rm, Rs, Rn", "\n INIT[CC]A Rm, Rn<br>\n IMLACPA Acc, Rs<br>\n IMLBCPA Acc, #0 <i>(14 times)</i><br>\n IMLBCPAS[F] Acc, #0 -> Rd", "No restrictions", "<em>Differs from ARM - V is corrupted</em>"); arm_emulation_table_end(); ?> <?php page_ep(); include "{$toplevel}web_assist/web_footer.php"; ?>
occur, whether they are forwards or backwards. </p> <p> Conditional branches with link are emulated by inserting two internal instructions in to the pipeline; one with the reverse condition of the instruction with flush to force a branch to PC+8-4 if the condition is not met, and the other with the current condition to set the link register on a correctly predicted branch. The program counter is also updated with the branch target address. </p> <?php page_section("emulation_details", "Emulation details"); arm_emulation_table_start(); arm_emulation_table_instruction("B {offset}", "", "Guaranteed branch", "Changes PC to PC+8+offset"); arm_emulation_table_instruction("B[CC] {offset}", "", "CC will be met<br>Guaranteed branch", "Changes PC to PC+8+offset"); arm_emulation_table_instruction("B[CC] {negative offset}", "SUB{!CC}F PC, #4 -> PC", "CC may not be met<br>Predicted branch", "Changes PC to PC+8+offset<br>If mispredicted then instruction will execute and reset PC to the correct path"); arm_emulation_table_instruction("B[CC] {positive offset}", "MOV{CC}F #target -> PC", "CC may not be met<br>Unpredicted branch", "If mispredicted then instruction will execute and set PC to branch target"); arm_emulation_table_instruction("BL {offset}", "SUB PC, #4 -> R14", "Guaranteed branch with link", "Changes PC to PC+8+offset"); arm_emulation_table_instruction("BL[CC] {offset}", "SUB PC, #4 -> R14", "CC will be met<br>Guaranteed branch with link", "Changes PC to PC+8+offset"); arm_emulation_table_instruction("BL[CC] {offset}", "SUB{!CC}F PC, #4 -> PC<br>SUB PC, #4 -> R14", "CC may not be met<br>Conditional branch with link", "Changes PC to PC+8+offset<br>If mispredicted then instruction will execute and reset PC to the correct path, and R14 will not be written"); arm_emulation_table_end(); page_ep(); include "{$toplevel}web_assist/web_footer.php"; ?>
<li> If the shift is by register Rs, then check if it should be replaced with ACC or PC: if it is R15 then replace it with 'PC', and the instruction address plus 8 will be passed in to the internal pipeline as the PC value; if instead it matches the tracking accumulator indicator then replace it with 'ACC'. If Rs is not replaced, then use it as is. This will be the second operand of the first internal instruction. <li> If the shift is immediate then use that as the second operand of the first internal instruction. </ol> <?php arm_emulation_table_start(); arm_emulation_table_instruction("MOV Rd, Rm, LSL #imm", "ILSL Rm, #imm<br>IMOVA SHF -> Rd", $rd_not_pc, "{$repl_shf}<br>{$move_ops}<br>{$effects_acc}"); arm_emulation_table_instruction("ADD Rd, Rn, Rm, LSL Rs", "ILSL Rm, Rs<br>IADDA Rn, SHF -> Rd", $rd_not_pc, "{$repl_shf}<br>{$repl_rn_rs}<br>{$arith_logic_ops}<br>{$effects_acc}"); arm_emulation_table_instruction("MOV PC, Rm, LSL Rs", "ILSL Rm, Rs<br>IMOVAF SHF -> PC", "", "{$repl_shf}<br>{$repl_rs}<br>{$move_ops}<br>{$effects_acc}"); arm_emulation_table_instruction("ADD PC, Rn, Rm, LSL #imm", "ILSL Rm, #imm<br>IADDAF Rn, SHF -> PC", "", "{$repl_shf}<br>{$repl_rn}<br>{$arith_logic_ops}<br>{$effects_nothing}"); arm_emulation_table_instruction("MOVS Rd, Rm, LSL #imm", "ILSL Rm, #imm<br>IMOVSPA SHF -> Rd", $rd_not_pc, "{$repl_shf}<br>{$move_ops}<br>{$effects_acc_zn}"); arm_emulation_table_instruction("CMP[S] Rn, Rm, LSL #imm", "ILSL Rm, #imm<br>ISUBSP Rn, SHF", "", "{$repl_shf}<br>{$repl_rn}<br>{$compare_ops}<br>{$effects_zcvn}"); arm_emulation_table_instruction("TST[S] Rn, Rm, LSL #imm", "ILSL Rm, #imm<br>IANDSP Rn, SHF", "", "{$repl_shf}<br>{$repl_rn}<br>{$compare_ops}<br>{$effects_zn}"); arm_emulation_table_instruction("ADDEQS Rd, Rn, Rm, LSL #imm", "ILSL Rm, #imm<br>IADDEQSP Rn, SHF -> Rd", $rd_not_pc, "{$repl_shf}<br>{$repl_rn}<br>{$arith_ops}<br>{$effects_acc_zcvn}<br>{$conds}"); arm_emulation_table_instruction("BICS Rd, Rn, Rm, LSL #imm", "ILSL Rm, #imm<br>IBICSPA Rn, SHF -> Rd", $rd_not_pc, "{$repl_shf}<br>{$repl_rn}<br>{$logic_ops}<br>{$effects_acc_zn}"); arm_emulation_table_end(); ?> </p> <?php page_ep(); include "{$toplevel}web_assist/web_footer.php"; ?>
arm_emulation_table_instruction("LDR[CC] Rd, [Rn], +/-Rm", "ILDR[CC]A[S] #0 (Rn), +/-Rm -> Rd<br>MOVCP ACC -> Rn", $rd_rn_not_pc, "{$repl_rn_rm}<br>"); arm_emulation_table_instruction("LDR[CC] PC, [Rn], +/-Rm", "ILDR[CC]A[S] #0 (Rn), +/-Rm -> PC<br>MOVCPF ACC -> Rn", $rn_not_pc, "{$repl_rn_rm}<br>"); arm_emulation_table_instruction("LDR[CC] Rd, [Rn], +/-Rm, SHF #imm", "ILSL Rm, #imm<br>ILDR[CC]A[S] #0 (Rn), +/-SHF -> Rd<br>MOVCP ACC -> Rn", $rd_rn_not_pc, "{$repl_rn_rm}<br>"); arm_emulation_table_instruction("LDR[CC] PC, [Rn], +/-Rm, SHF #imm", "ILSL Rm, #imm<br>ILDR[CC]A[S] #0 (Rn), +/-SHF -> PC<br>MOVCPF ACC -> Rn", $rn_not_pc, "{$repl_rn_rm}<br>"); arm_emulation_table_end(); ?> <?php page_section("stores", "Stores"); arm_emulation_table_start(); arm_emulation_table_instruction("STR[CC] Rd, [Rn, #0]", "ISTR[CC][S] #0 (Rn) <- Rd", "", $repl_rn); arm_emulation_table_instruction("STR[CC] Rd, [Rn, #0]!", "ISTR[CC][S] #0 (Rn) <- Rd", "", $repl_rn); arm_emulation_table_instruction("STR[CC] Rd, [Rn], #0", "ISTR[CC][S] #0 (Rn) <- Rd", "", $repl_rn); arm_emulation_table_instruction("STR[CC] Rd, [Rn, #+/-imm]", "IADD[CC]AC/ISUB[CC]AC Rn, #imm<br>ISTRCP[S] #0 (ACC, +/-SHF) <- Rd", "", $repl_rn); arm_emulation_table_instruction("STR[CC] Rd, [Rn, +/-Rm]", "IADD[CC]AC/ISUB[CC]AC Rn, Rm<br>ISTRCP[S] #0 (ACC, +/-SHF) <- Rd", "", $repl_rn_rm); arm_emulation_table_instruction("STR[CC] Rd, [Rn, +/-Rm, SHF #imm]", "ISHF[CC] Rm, #imm<br>ISTRCPA[S] #0 (Rn, +/-SHF) <- Rd", "", $repl_rn_rm); arm_emulation_table_instruction("STR[CC] Rd, [Rn, #+/-imm]!", "IADDAC/ISUBAC Rn, #imm<br>ISTR[CC]A[S] #0 (ACC, +SHF) <- Rd -> Rn", "", $repl_rn); arm_emulation_table_instruction("STR[CC] Rd, [Rn, +/-Rm]!", "IADDAC/ISUBAC Rn, Rm<br>ISTR[CC]A[S] #0 (ACC, +SHF) <- Rd -> Rn", "", $repl_rn_rm); arm_emulation_table_instruction("STR[CC] Rd, [Rn, +/-Rm, SHF #imm]!", "ILSL Rm, #imm<br>ISTR[CC]A[S] #0 (Rn, +/-SHF) <- Rd -> Rn", "", $repl_rn_rm); arm_emulation_table_instruction("STR[CC] Rd, [Rn], #+/-imm", "ISTR[CC][S] #0 (Rn) <- Rd<br>IADDCPA/ISUBCPA Rn, #imm -> Rn", "", $repl_rn); arm_emulation_table_instruction("STR[CC] Rd, [Rn], +/-Rm", "ISTR[CC][S] #0 (Rn) <- Rd<br>IADDCPA/ISUBCPA Rn, Rm -> Rn", "", $repl_rn_rm); arm_emulation_table_instruction("STR[CC] Rd, [Rn], +/-Rm, SHF #imm", "ISHF[CC] Rm, #imm<br>ISTRCPA[S] #0 (Rn), +/-SHF <- Rd -> Rn", "", $repl_rn_rm); arm_emulation_table_end(); ?> <?php page_ep(); include "{$toplevel}web_assist/web_footer.php"; ?>
arm_emulation_table_instruction("LDM[CC]IA Rn, {Ri0, Ri1, ... Rik}", "ILDR[CC]A[S] #k (Rn), #+4 -> Ri0<br>ILDRCPA[S] #k-1 (Acc), #+4 -> Ri1<br>...<br>ILDRCPA[A][F] #0 (Acc), #+4 -> Rik", $rn_not_pc, $repl_rn); arm_emulation_table_instruction("LDM[CC]IA Rn!, {Ri0, Ri1, ... Rik}", "ILDR[CC]A[S] #k (Rn), #+4 -> Ri0<br>ILDRCPA[S] #k-1 (Acc), #+4 -> Ri1<br>...<br>ILDRCPA[S] #0 (Acc), #+4 -> Rik<br>IMOVCP[F] Acc -> Rn", $rn_not_pc, $repl_rn); arm_emulation_table_instruction("LDM[CC]IB Rn, {Ri0, Ri1, ... Rik}", "ILDR[CC]A[S] #k (Rn, #+4) -> Ri0<br>ILDRCPA[S] #k-1 (Acc, #+4) -> Ri1<br>...<br>ILDRCPA[S][F] #0 (Acc, #+4) -> Rik", $rn_not_pc, $repl_rn); arm_emulation_table_instruction("LDM[CC]IB Rn!, {Ri0, Ri1, ... Rik}", "ILDR[CC]A[S] #k (Rn, #+4) -> Ri0<br>ILDRCPA[S] #k-1 (Acc, #+4) -> Ri1<br>...<br>ILDRCPA[S] #0 (Acc, #+4) -> Rik<br>IMOVCP[F] Acc -> Rn", $rn_not_pc, $repl_rn); arm_emulation_table_instruction("LDM[CC]DB Rn, {Ri0, Ri1, ... Rik}", "ISUB[CC]A Rn, #k*4<br>ILDRCPA[S] #k (Acc), #+4 -> Ri0<br>ILDRCPA[S] #k-1 (Acc), #+4 -> Ri1<br>...<br>ILDRCPA[S][F] #0 (Acc), #+4 -> Rik", $rn_not_pc, $repl_rn); arm_emulation_table_instruction("LDM[CC]DB Rn!, {Ri0, Ri1, ... Rik}", "ISUB[CC]A Rn, #k*4 -> Rn<br>ILDRCPA[S] #k (Acc), #+4 -> Ri0<br>ILDRCPA[S] #k-1 (Acc), #+4 -> Ri1<br>...<br>ILDRCPA[S][F] #0 (Acc), #+4 -> Rik", $rn_not_pc, $repl_rn); arm_emulation_table_instruction("LDM[CC]DA Rn, {Ri0, Ri1, ... Rik}", "ISUB[CC]A Rn, #k*4<br>ILDRCPA[S] #k (Acc, #+4) -> Ri0<br>ILDRCPA[S] #k-1 (Acc, #+4) -> Ri1<br>...<br>ILDRCPA[S][F] #0 (Acc, #+4) -> Rik", $rn_not_pc, $repl_rn); arm_emulation_table_instruction("LDM[CC]DA Rn!, {Ri0, Ri1, ... Rik}", "ISUB[CC]A Rn, #k*4 -> Rn<br>ILDRCPA[S] #k (Acc, #+4) -> Ri0<br>ILDRCPA[S] #k-1 (Acc, #+4) -> Ri1<br>...<br>ILDRCPA[S][F] #0 (Acc, #+4) -> Rik", $rn_not_pc, $repl_rn); arm_emulation_table_end(); ?> <?php page_section("stores", "Stores"); arm_emulation_table_start(); arm_emulation_table_instruction("STM[CC]IA Rn, {Ri0, Ri1, ... Rik}", "ISTR[CC]A[S] #k (Rn), #+4 <- Ri0<br>ISTRCPA[S] #k-1 (Acc), #+4 <- Ri1<br>...<br>ISTRCPA[S] #0 (Acc), #+4 <- Rik", $rn_not_pc, $repl_rn); arm_emulation_table_instruction("STM[CC]IA Rn!, {Ri0, Ri1, ... Rik}", "ISTR[CC]A[S] #k (Rn), #+4 <- Ri0<br>ISTRCPA[S] #k-1 (Acc), #+4 <- Ri1<br>...<br>ISTRCPA[S] #0 (Acc), #+4 <- Rik -> Rn", $rn_not_pc, $repl_rn); arm_emulation_table_instruction("STM[CC]IB Rn, {Ri0, Ri1, ... Rik}", "ISTR[CC]A[S] #k (Rn, #+4) <- Ri0<br>ISTRCPA[S] #k-1 (Acc, #+4) <- Ri1<br>...<br>ISTRCPA[S] #0 (Acc, #+4) <- Rik", $rn_not_pc, $repl_rn); arm_emulation_table_instruction("STM[CC]IB Rn!, {Ri0, Ri1, ... Rik}", "ISTR[CC]A[S] #k (Rn, #+4) <- Ri0<br>ISTRCPA[S] #k-1 (Acc, #+4) <- Ri1<br>...<br>ISTRCPA[S] #0 (Acc, #+4) <- Rik -> Rn", $rn_not_pc, $repl_rn); arm_emulation_table_instruction("STM[CC]DB Rn, {Ri0, Ri1, ... Rik}", "ISUB[CC]A Rn, #k*4<br>ISTRCPA[S] #k (Acc), #+4 <- Ri0<br>ISTRCPA[S] #k-1 (Acc), #+4 <- Ri1<br>...<br>ISTRCPA[S] #0 (Acc), #+4 <- Rik", $rn_not_pc, $repl_rn); arm_emulation_table_instruction("STM[CC]DB Rn!, {Ri0, Ri1, ... Rik}", "ISUB[CC]A Rn, #k*4 -> Rn<br>ISTRCPA[S] #k (Acc), #+4 <- Ri0<br>ISTRCPA[S] #k-1 (Acc), #+4 <- Ri1<br>...<br>ISTRCPA[S] #0 (Acc), #+4 <- Rik", $rn_not_pc, $repl_rn); arm_emulation_table_instruction("STM[CC]DA Rn, {Ri0, Ri1, ... Rik}", "ISUB[CC]A Rn, #k*4<br>ISTRCPA[S] #k (Acc, #+4) <- Ri0<br>ISTRCPA[S] #k-1 (Acc, #+4) <- Ri1<br>...<br>ISTRCPA[S] #0 (Acc, #+4) <- Rik", $rn_not_pc, $repl_rn); arm_emulation_table_instruction("STM[CC]DA Rn!, {Ri0, Ri1, ... Rik}", "ISUB[CC]A Rn, #k*4 -> Rn<br>ISTRCPA[S] #k (Acc, #+4) <- Ri0<br>ISTRCPA[S] #k-1 (Acc, #+4) <- Ri1<br>...<br>ISTRCPA[S] #0 (Acc, #+4) <- Rik", $rn_not_pc, $repl_rn); arm_emulation_table_end(); ?> <?php page_ep(); include "{$toplevel}web_assist/web_footer.php"; ?>