beq

beq

Assembly RISC-V Referência

lyszt.net aborda beq e outras instruções RISC-V com mais detalhes.

Formato de codificação

R
31–25funct7
24–20rs2
19–15rs1
14–12funct3
11–7rd
6–0opcode
I
31–20imm[11:0]
19–15rs1
14–12funct3
11–7rd
6–0opcode
S
31–25imm[11:5]
24–20rs2
19–15rs1
14–12funct3
11–7imm[4:0]
6–0opcode
B
31–25imm[12,10:5]
24–20rs2
19–15rs1
14–12funct3
11–7imm[4:1,11]
6–0opcode
U
31–12imm[31:12]
11–7rd
6–0opcode
J
31–12imm[20,10:1,11,19:12]
11–7rd
6–0opcode

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'