I am currently writing an Intel 8042 driver and have written two loops to wait until some buffers are ready for use:
/* Waits until the Intel 8042's input buffer is empty, i.e., until the
* controller has processed the input. */
i8042_waitin:
pause
in $i8042_STATUS, %al
and $i8042_STAT_INEMPTY, %al
jz i8042_waitin
ret
/* Waits until the Intel 8042's output buffer is full, i.e., data to read is
* available.
* ATTENTION: this here is the polling variant but there is also a way with
* interrupts! By setting bit 0 in the command byte you can enable an interrupt
* to be fired when the output buffer is full. */
i8042_waitout:
pause
in $i8042_STATUS, %al
and $i8042_STAT_OUTFULL, %al
jz i8042_waitout
ret
As you can see, I inserted pause
instructions in the loops. I've just recently learned about it and wanted to try it out, naturally.
Since the content of %al
is unpredictable because it's an I/O read, the branch predictor will fill the pipeline with instructions of the loop: after some iterations, it will notice always one branch is taken, similarly to the case here.
The above is correct if the branch predictor really includes I/O instructions in its prediction, which I am not sure of.
So does the branch predictor adjust itsself using the result of I/O instructions as is the case with unpredictable memory reads? Or is there something else going on here?
Does pause
make sense here?