Estamos agora pronto para descrever o ciclo de interpretação de instrução. Vamos primeiro agrupar o que foi visto em termos de interpretação de cada instrução em um procedimento IExec, como abaixo:
IExec\Instruction.Execution:= Begin If Op Eql 0 => Acc <- Acc And Mp[Z()]; If Op Eql 1 => Acc <- Acc + Mp[Z()]; If Op Eql 2 => Begin Mp[Z] <- Mp[Z()] + 1 Next If Mp[Z] Eql 0 => PC <- PC+1 End; If Op Eql 3 => Mp[Z()]@Acc <- Acc@#0000; If Op Eql 4 => Stop(); If Op Eql 5 => PC <- Z(); If Op Eql 6 => Stop(); If Op Eql 7 => Stop() End
O ciclo de interpretação de instruções pode agora ser descrito como
ICycle\Interpretation.Cycle:= Begin Repeat Begin IR <- Mp[PC] Next PC <- PC + 1 Next IExec() Next If Interrupt.Enable And Interrupt.Request => Begin Mp[0] <- PC Next PC <- 1 End End End
Em cada ciclo de interpretação de instrução, uma
instrução é buscada da posição PC da memória e
carregada em IR. O valor de PC é atualizada. A instrução é
então executada pela chamada IExec(). Se os bits Interrupt.Enable e
Interrupt.Request estão ambos ligados, então significa que há
um pedido de interrupção e o processador pode atender a tal
pedido. Nesse caso, o valor do PC é guardado em Mp[0] e o PC passa
a conter 1. A instrução da palavra 1 da memória será
então executada, para tratar a interrupção.
E interessante verificar o que deve conter a palavra 1 da memória, onde inicia a rotina de tratamento de interrupção. A rotina de interrupção deve salvar primeiro as informações relevantes do processador (também chamado o contexto da máquina) e somente depois disso pode ir tratar a interrupção em questão. Note-se que antes de salvar o contexto, não podemos permitir nova interrupção. Assim, devemos colocar na palavra 1 uma instrução que inibe novas interrupções. Podemos usar o código de operação 6 para isso:
If Op Eql 6 => Interrupt.Enable <- 0;
Quando terminamos o tratamento da interrupção, devemos colocar em PC o valor guardado, para retornar ao ponto suspenso antes de acontecer a interrupção. Antes disso, porém, devemos permitir interrupções de novo, fazendo Interrupt.Enable igual a 1. Para isso, vamos usar o código de operação 7:
If Op Eql 7 => Begin Interrupt.Enable <- 1 Next Restart ICycle End
O Restart significa ir para o começo do ciclo de
interpretação de instrução. Isso é fundamental para que
após a execução da instrução 7 (habilitando a
interrupção), não se testem os bits Interrupt.Enable (que
acabou de ficar 1) e Interrupt.Request (que pode ser 1, significando
uma interrupção pendente). Por que? Porque antes de atender
qualquer interrupção, queremos garantir a execução de
mais uma instrução, que restaura o valor do PC guardado.
Podemos reescrever IExec usando Decode Op, incluindo as instruções 6 e 7, e acrescentano mnemônicos para as instruções.
IExec\Instruction.Execution:= Begin Decode Op => Begin 0\AND:= Acc <- Acc And Mp[Z()], 1\TAD:= Acc <- Acc + Mp[Z()], !Two's complement add 2\ISZ:= !Increment and skip if zero Begin Mp[Z] <- Mp[Z()] + 1 Next If Mp[Z] Eql 0 => PC <- PC+1 End, 3\DCA:= Mp[Z()]@Acc <- Acc@#0000, !Deposit and clear Acc 4\HLT:= Stop(), !Halt 5\JMP:= PC <- Z(), !Jump 6\IOF:= Interrupt.Enable <- 0, !Interrupt OFF 7\ION:= !Interrupt ON Begin Interrupt.Enable <- 1 Next Restart ICycle End End End