O Conjunto de Instruções ISA – Instruction Set Architecture 1 Conjunto de instruções Alguns conceitos... Linguagem máquina Linguagem assembly Combinação de ‘0’s e ‘1’s organizados segundo palavras que são as instruções que o processador percebe Linguagem que permite uma correspondência directa ao código máquina, e que para todos os efeitos é mais fácil de programar do que escrever directamente os ‘0’s e ‘1’s Arquitectura Hardware (circuitos) Organização (datapath, unidade de controlo) Conjunto de instruções ou ISA – Instruction Set Architecture 2 Conjunto de instruções Até agora, lidámos com o conjunto de instruções do processador MAC-1 É preciso ter em conta que CPUs diferentes têm arquitecturas diferentes e conjuntos de instruções diferentes Por exemplo, o conjunto de instruções de um processador Intel Core 2 Duo é diferente do conjunto de instruções de um processador ARM (usado em telemóveis) Mas apesar de os conjuntos de instruções serem diferentes, os tipos de instruções disponíveis em cada conjunto são idênticos 3 Instruções típicas Transferências de dados Instrução Mnemónica Load LD, LW Store ST, LW Transferir (mover) MOV Push PUSH Pop POP Trocar XCH, SWAP Notas: Tipicamente, quando são utilizadas instruções do tipo Load / Store, a instrução MOV apenas permite transferências entre registos (ou então não existe). 4 Instruções típicas Aritméticas Instrução Mnemónica Notas: Incrementar INC Decrementar DEC Geralmente existem instruções distintas para inteiros e reais (vírgula flutuante) Somar ADD Exemplo: Subtrair SUB IADD (inteiros) Multiplicar MUL FADD (vírgula flutuante) Dividir DIV Simétrico NEG Atenção a NEG, cuja finalidade costuma ser calcular o simétrico (complemento para 2) e não a negação... 5 Instruções típicas Lógicas Instrução Mnemónica Notas: Clear CLR CLR – colocar um registo a ‘0’ Set SET SET – colocar um registo a ‘1’ Negação NOT AND AND OR XOR OR XOR Existem tipicamente outros tipos de CLRs e SETs que visam colocar a ‘0’ ou a ‘1’ apenas um bit do estado (flag) da unidade funcional 6 Instruções típicas Controlo de programa Instrução Jump Jump if equal Jump if not equal Jump if zero Jump if not zero Jump if above etc... Mnemónica JMP JE JNE Notas: Muitos processadores utilizam a designação branch em vez de jump. Na maioria das vezes as designações são sinónimas. JZ JNZ JA Noutros podem existir diferenças: por exemplo, jump poderia ser um salto para um endereço absoluto e branch um salto para um endereço relativo. 7 Instruções típicas Procedimentos Instrução Mnemónica Chamar procedimento CALL Retornar RETN CALL / RETN – o endereço de retorno é colocado / lido da pilha. Instrução Mnemónica Jump and link JAL Jump register JR JAL / JR – o endereço de retorno é colocado / lido de num registo. 8 Formatos de instrução As instruções encontram-se organizadas segundo campos com significado específico: Código de operação (opcode) Indica qual é o tipo ou finalidade da instrução Operandos Origem e destino dos dados (endereços ou registos) Valores constantes que vão na própria instrução Modo de endereçamento Indica o modo como devem ser interpretados os operandos Muitas vezes está incluído no próprio opcode e não num campo em separado Opcode Modo Operando 1 Operando 2 9 Formatos de instrução Exemplos de algumas instruções já conhecidas LODD x 0 0 0 0 x x x x Opcode (4 bits) x x x x x x x c c c c y y y y Posição de memória a ler (12 bits) LOCO c 0 1 1 1 c c c c Opcode (4 bits) x c c c c Constante a carregar (12 bits) INSP y 1 1 1 Opcode (4 bits) 1 1 1 0 0 Exp. do opcode (4 bits) y y y y Posição de memória a ler (12 bits) 10 Formatos de instrução É habitual classificar os formatos de instrução de acordo com o número de operandos 1, 2, ou 3 operandos …ou mesmo sem operandos (muito usadas em arquitecturas baseadas em stack) Exemplo: Considere que se pretende calcular: M[x] ← (M[a] + M[b]) (M[c] - M[d]) 11 Formatos de instrução com 3 operandos... Pode-se especificar um destino e duas fontes Opcode Destino Fonte 1 ADD R1, a, b # R1 ← M[a] + M[b] SUB R2, c, d # R2 ← M[c]+ M[d] MUL x, R1, R2 # M[x] ← R1 R2 Fonte 2 Nota: Assumiu-se que as fontes / destino dos dados podem ser endereços ou registos. Como veremos mais à frente, não é uma assunção muito realista, uma vez que obriga a instruções com comprimento demasiado longo. 12 Formatos de instrução com 2 operandos... Especifica-se uma fonte e um destino Opcode MOV R1, a ADD R1, b MOV R2, c SUB R2, d MUL R1, R2 MOV x, R2 Destino Fonte 1 # R1 ← M[a] # R1 ← R1 + M[b] # R2 ← M[c] # R2 ← R2 – M[d] # R1 ← R1 R2 # M[x] = R2 Nota: assumiu-se que o registo destino acumula resultados, pelo que serve de fonte, de uma forma implícita 13 Formatos de instrução com 1 operando... Vão sendo guardados os resultados num registo acumulador Especifica-se apenas uma fonte ou um destino Opcode Destino ou fonte LOAD a ADD b STORE x LOAD c SUB d MUL x STORE x # AC ← M[a] # AC ← AC + M[b] # M[x] ← AC # AC ← M[c] # AC ← AC + M[d] # AC ← AC M[x] # M[x] ← AC 14 Formatos de instrução sem operandos... Todas as operações são feitas com recurso à pilha As instruções fazem implicitamente pop dos operandos e push dos resultados PUSH a PUSH b ADD PUSH c PUSH d SUB MUL POP x # TOS ← M[A] # TOS ← M[B] # TOS ← TOS-1 + TOS # TOS ← M[C] # TOS ← M[D] # TOS ← TOS-1 – TOS # TOS ← TOS-1 TOS # M[X] ← TOS TOS – Topo da Pilha (Top of Stack) TOS-1 – 2º valor na pilha (a contar do topo) 15 Formatos de instrução Curiosidade… Para facilitar a implementação de código sem operandos, pode-se utilizar a notação RPN (Reverse Polish Notation) Exemplo: a expressão (A+B) (C-D) é equivalente à seguinte, em RPN: AB+CD- A ordem pela qual aparecem os operandos e as operações em RPN é a mesma que se segue num programa idêntico ao anterior 16 Formatos de instrução Como maximizar o número de instruções do conjunto? Expansão do opcode Aproveita-se o facto de nem todas as instruções terem o mesmo número de operandos Para se expandir o opcode, usa-se o espaço deixado por campos que não são utilizados Resulta assim um opcode com mais bits, possibilitando um maior número de instruções Instruções de comprimento variável A ideia é ter instruções cujo comprimento varia consoante as necessidades (exemplo: dentro do mesmo conjunto, ter instruções de 16, 32 e 64 bits) 17 Formatos de instrução Exemplo de expansão do opcode Vamos supor que se pretende projectar um conjunto de instruções com os seguintes formatos: Formato I Opcode Operando 1 Operando 2 4 bits 8 bits 8 bits Formato II Opcode 4 bits Operando 1 2 bits 10 bits Quantas Instruções serão possíveis para cada um dos formatos ? 18 Formatos de instrução Exemplo de expansão do opcode (cont.) Se fossem todas do formato I teríamos 24 = 16 instruções diferentes Aproveitando o espaço de 2 bits disponíveis no formato II para expansão do opcode, existem outras possibilidades: 15 de formato I + 4 do formato II 14 de formato I + 8 do formato II 13 de formato I + 12 do formato II … De uma forma geral teríamos, neste caso: 24–k instruções do formato I + k22 instruções do formato II Repare que os expoentes ‘4’ e ‘2’ correspondem ao número de bits do opcode e da expansão, respectivamente 19 Formatos de instrução Algumas considerações… Em geral, se um conjunto de instruções permite mais operandos, menor será o número de instruções num programa No entanto, maior será o comprimento das instruções, de forma a incluir todos os operandos necessários Quanto menor for o comprimento das instruções, Maior rapidez a efectuar o fetch (pois podem ser lidas mais instruções de uma só vez) Haverá mais instruções, mas na prática irão ocupar menos espaço, pois são mais pequenas Mais difícil será a possibilidade de futuras expansões ao conjunto de instruções (factor importante do ponto de vista comercial) O normal é tentar que chegar a uma solução de compromisso 20 Formatos de instrução Alguns exemplos reais Intel (x86) – max. 2 operandos PowerPC (Wii, Xbox 360) – max. 3 operandos Cell (Playstation 3) – max. 4 operandos (maioria 3) TMS (Processador de sinal) – max. 3 operandos ARM – max. 3 operandos (maioria 2) ...e virtuais Java Virtual Machine – a maioria sem operandos MAC-1– max. 1 operando MIPS – max. 3 operandos 21 Modos de endereçamento Implícito Com base no opcode, o processador fica a saber implicitamente onde estão os dados envolvidos na operação Imediato Constante que é dada na própria instrução Exemplo: instruções PUSH e POP Exemplos: R1 ← constante, instrução LOCO do MAC-1 Directo Indica a posição de memória onde estão os valores envolvidos na operação Exemplos: R1 ← M[x], instruções LODD e ADDD do MAC-1 22 Modos de endereçamento Registo directo Indica o registo onde se encontram os dados Registo indirecto Especifica-se um registo e o valor guardado nesse registo é posição de memória onde estão os dados Exemplo: R1 ← R2 Eficiente, pois não são feitos acessos à memória Exemplos: R1 ← M[R2], instruções PSHI e POPI do MAC-1 Útil para indexar vectores Indirecto Especifica-se uma posição de memória - o conteúdo dessa posição de memória dá uma outra posição onde estão localizados os dados São necessários dois acessos à memória Exemplo: R1 ← M[ M[x] ] Útil para aceder a listas e a matrizes bidimensionais 23 Modos de endereçamento Duplamente indirecto Semelhante ao anterior, mas a primeira posição a aceder é dada por um registo Exemplo: R1 ← M[ M[R2] ] Indexado Acede-se à posição de memória dada pela soma do conteúdo de um registo com um deslocamento (offset) indicado na instrução Exemplos: R1← M[R2 + offset], instruções LODL, ADDL do MAC-1 Útil para indexar vectores e gerir variáveis locais Existem outras designações para este modo: Endereçamento Local ou Baseado – quando é relativo ao Stack Pointer Endereçamento Relativo – quando é relativo ao Program Counter 24 Modos de endereçamento Possível notação para indicar os modos de endereçamento Modo Notação Efeito Imediato MOV R1, #N R1 ← N Directo MOV R1, addr R1 ← M[addr] Indirecto MOV R1, [addr] R1 ← M[M[addr]] Registo-directo MOV R2, R1 R2 ← R1 Registo-indirecto MOV R2, [R1] R2 ← M[R1] Indexado MOV R2, addr[R1] R2 ← M[addr+R1] Duplamente indirecto MOV R2, [[R1]] R2 ← M[M[R1]] 25 Modos de endereçamento Memória Exemplo Qual será o valor em R2 após… MOV R2, #2 MOV R2, 2 R2 = 2 R2 = 6 MOV R2, R1 R2 = 5 MOV R2, [R1] R2 = 3 MOV R2, 2[R1] R2 = 11 MOV R2, [2] R2 = 45 0 1 2 3 4 5 6 7 8 9 10 xx 10 6 8 27 3 45 11 12 13 14 xx R1 5 R2 ??? 26