beq
lyszt.net aborda beq e outras instruções RISC-V com mais detalhes.
Formato de codificação
Descrição
beq permite que um programa tome uma decisão. O processador normalmente executa as instruções na ordem em que aparecem na lista. Essa ordem por si só não consegue escolher nem repetir nada. Um desvio altera a ordem. Ele testa uma condição e, se a condição for verdadeira, o processador continua em um lugar diferente em vez da próxima linha. Todas as instruções if e laços são construídos a partir de desvios.
O lugar diferente é nomeado por um rótulo, um nome seguido de dois-pontos que marca uma posição no código, como o rótulo done no exemplo. beq (branch if equal, desviar se igual) compara dois registradores. Quando eles contêm o mesmo valor, ele salta para a posição rotulada; quando diferem, a execução continua com a próxima instrução. A forma aparece abaixo.
beq rs1, rs2, label
beq apenas muda qual instrução é executada em seguida. Armazenar o resultado sim ou não de uma comparação como um número exige uma instrução diferente, descrita na página slt.
O processador acompanha sua posição com um registrador chamado contador de programa, que contém o endereço da instrução que está em execução. Um desvio tomado altera esse endereço, de modo que a próxima instrução vem do rótulo.
O manual do RISC-V afirma que um desvio condicional armazena seu deslocamento como um valor de 12 bits contado em múltiplos de 2 bytes. O deslocamento é estendido com sinal e somado ao endereço da instrução de desvio, resultando em um alcance de mais ou menos 4 KiB, onde um KiB é 1024 bytes. As instruções de desvio comparam dois registradores diretamente e não usam códigos de condição. O manual apresenta a razão de que uma instrução combinada de comparação e desvio se encaixa em um pipeline regular e não precisa de estado extra nem de registrador temporário. Ele também aconselha o software a manter o caminho mais comum como código reto e a esperar que desvios para trás sejam previstos como tomados e desvios para frente como não tomados, pelo menos na primeira vez em que forem encontrados.
Um desvio compara dois registradores e não pode usar uma constante escrita na instrução, portanto uma forma como beq t0, 5, label não existe. Para comparar um registrador com uma constante, carregue a constante em um registrador primeiro com li, depois compare os dois registradores.
li t1, 5 beq t0, t1, done
O valor 0 não precisa ser carregado, porque o registrador zero sempre o contém.
Um uso comum compara um registrador com zero, o registrador que sempre contém 0, para perguntar se um valor chegou a zero. Isso encerra laços de contagem regressiva e verifica resultados. O exemplo desvia para done quando a0 contou regressivamente até zero. beq e rótulos são suficientes para construir toda decisão e todo laço em um programa.
Exemplo
beq a0, zero, done # if a0 == 0, jump to 'done'
