The original BASIC used the IO(x) keyword to control pins.   It was simple and handled both reading and writing pins.  If the IO is on the left hand side of an = sign, then the pin is made into an output and the pin is set high when the expression on the right hand side of the = is not 0, or set low when the right hand side is 0.  When the IO is on the right hand side of an = sign, then the pin is converted to an input and the value of the pin is read.  IO(x) also controls pin direction (input vs. output).  Reading the pin turns it to an input, and you can always ignore the data.

When PBASIC support was added for the ARMexpress, the IN, OUT, INPUT, OUTPUT, HIGH, LOW and DIR keywords were added.  Yes a lot of complexity, but the intention was to be compatible with PBASIC.  These keywords are still available and will remain so.  IN  will always read the state of the pin, whether the pin is configured as an input or output.  OUT will set the pin only if the pin has been configured as an output.  Both IN and OUT are faster than IO, HIGH and LOW keywords that also configure the pin direction.

It's unfortunate that INPUT was used, as for most early BASICs this was used to get user input for a program, a function now handled by DEBUGIN.  For those who'd like to use INPUT for that you could always do

   #define INPUT   DEBUGIN

To match the BASIC Stamp, pins were mapped to port bits that did not correspond to the NXP bit assignments.  This was also done for the ARMmite and original PRO board.  But with all future boards, the NXP bit assignment will be used.

With the use by NXP of multiple 32 bit ports for IO pins, it was necessary to expand controls.  P0(x) through P5(x) keywords have been added.  The compiler optimizes code for these keywords, and generates inline code to increase performance.  Because this code is inline it will be faster, but also larger.

With version 7.50 for ARM7 and 8.12 for ARM Cortex parts, the original keywords IO, IN OUT, INPUT, OUTPUT, DIR, HIGH and LOW have been expanded to handle multiple ports, by defining bits 32 through 63 as port P1, 64 through 95 as port P2... These keywords call built-in functions.  So the code for these will be smaller, but also slower.

If you want to control or read multiple pins, you can always access the FIOxPIN register directly using pointers.  Details on how the pins work are in the NXP User Manual for the appropriate part.

See also