diff mbox

[pic32,v2,5/5] Two new machine platforms: pic32mz7 and pic32mz.

Message ID 16270e45922ea6a8c8622e76f702c46ce7ce15ac.1435723168.git.serge.vakulenko@gmail.com
State New
Headers show

Commit Message

Serge Vakulenko July 1, 2015, 4:12 a.m. UTC
Signed-off-by: Serge Vakulenko <serge.vakulenko@gmail.com>
---
 hw/mips/Makefile.objs       |    3 +
 hw/mips/mips_pic32mx7.c     | 1652 +++++++++++++++++++++++++
 hw/mips/mips_pic32mz.c      | 2840 +++++++++++++++++++++++++++++++++++++++++++
 hw/mips/pic32_ethernet.c    |  557 +++++++++
 hw/mips/pic32_gpio.c        |   39 +
 hw/mips/pic32_load_hex.c    |  238 ++++
 hw/mips/pic32_peripherals.h |  210 ++++
 hw/mips/pic32_sdcard.c      |  428 +++++++
 hw/mips/pic32_spi.c         |  121 ++
 hw/mips/pic32_uart.c        |  228 ++++
 hw/mips/pic32mx.h           | 1290 ++++++++++++++++++++
 hw/mips/pic32mz.h           | 2093 +++++++++++++++++++++++++++++++
 12 files changed, 9699 insertions(+)
 create mode 100644 hw/mips/mips_pic32mx7.c
 create mode 100644 hw/mips/mips_pic32mz.c
 create mode 100644 hw/mips/pic32_ethernet.c
 create mode 100644 hw/mips/pic32_gpio.c
 create mode 100644 hw/mips/pic32_load_hex.c
 create mode 100644 hw/mips/pic32_peripherals.h
 create mode 100644 hw/mips/pic32_sdcard.c
 create mode 100644 hw/mips/pic32_spi.c
 create mode 100644 hw/mips/pic32_uart.c
 create mode 100644 hw/mips/pic32mx.h
 create mode 100644 hw/mips/pic32mz.h

Comments

Aurelien Jarno July 1, 2015, 1:41 p.m. UTC | #1
On 2015-06-30 21:12, Serge Vakulenko wrote:
> Signed-off-by: Serge Vakulenko <serge.vakulenko@gmail.com>
> ---
>  hw/mips/Makefile.objs       |    3 +
>  hw/mips/mips_pic32mx7.c     | 1652 +++++++++++++++++++++++++
>  hw/mips/mips_pic32mz.c      | 2840 +++++++++++++++++++++++++++++++++++++++++++
>  hw/mips/pic32_ethernet.c    |  557 +++++++++
>  hw/mips/pic32_gpio.c        |   39 +
>  hw/mips/pic32_load_hex.c    |  238 ++++
>  hw/mips/pic32_peripherals.h |  210 ++++
>  hw/mips/pic32_sdcard.c      |  428 +++++++
>  hw/mips/pic32_spi.c         |  121 ++
>  hw/mips/pic32_uart.c        |  228 ++++
>  hw/mips/pic32mx.h           | 1290 ++++++++++++++++++++
>  hw/mips/pic32mz.h           | 2093 +++++++++++++++++++++++++++++++
>  12 files changed, 9699 insertions(+)
>  create mode 100644 hw/mips/mips_pic32mx7.c
>  create mode 100644 hw/mips/mips_pic32mz.c
>  create mode 100644 hw/mips/pic32_ethernet.c
>  create mode 100644 hw/mips/pic32_gpio.c
>  create mode 100644 hw/mips/pic32_load_hex.c
>  create mode 100644 hw/mips/pic32_peripherals.h
>  create mode 100644 hw/mips/pic32_sdcard.c
>  create mode 100644 hw/mips/pic32_spi.c
>  create mode 100644 hw/mips/pic32_uart.c
>  create mode 100644 hw/mips/pic32mx.h
>  create mode 100644 hw/mips/pic32mz.h

This patch is huge, and needs to be splitted to ease the review.
Antony Pavlov July 2, 2015, 5:56 a.m. UTC | #2
On Tue, 30 Jun 2015 21:12:34 -0700
Serge Vakulenko <serge.vakulenko@gmail.com> wrote:

> Signed-off-by: Serge Vakulenko <serge.vakulenko@gmail.com>
> ---
>  hw/mips/Makefile.objs       |    3 +
>  hw/mips/mips_pic32mx7.c     | 1652 +++++++++++++++++++++++++
>  hw/mips/mips_pic32mz.c      | 2840 +++++++++++++++++++++++++++++++++++++++++++
>  hw/mips/pic32_ethernet.c    |  557 +++++++++
>  hw/mips/pic32_gpio.c        |   39 +
>  hw/mips/pic32_load_hex.c    |  238 ++++
>  hw/mips/pic32_peripherals.h |  210 ++++
>  hw/mips/pic32_sdcard.c      |  428 +++++++
>  hw/mips/pic32_spi.c         |  121 ++
>  hw/mips/pic32_uart.c        |  228 ++++
>  hw/mips/pic32mx.h           | 1290 ++++++++++++++++++++
>  hw/mips/pic32mz.h           | 2093 +++++++++++++++++++++++++++++++
>  12 files changed, 9699 insertions(+)
>  create mode 100644 hw/mips/mips_pic32mx7.c
>  create mode 100644 hw/mips/mips_pic32mz.c
>  create mode 100644 hw/mips/pic32_ethernet.c
>  create mode 100644 hw/mips/pic32_gpio.c
>  create mode 100644 hw/mips/pic32_load_hex.c
>  create mode 100644 hw/mips/pic32_peripherals.h
>  create mode 100644 hw/mips/pic32_sdcard.c
>  create mode 100644 hw/mips/pic32_spi.c
>  create mode 100644 hw/mips/pic32_uart.c
>  create mode 100644 hw/mips/pic32mx.h
>  create mode 100644 hw/mips/pic32mz.h
> 
> diff --git a/hw/mips/Makefile.objs b/hw/mips/Makefile.objs
> index 9633f3a..dcbaec9 100644
> --- a/hw/mips/Makefile.objs
> +++ b/hw/mips/Makefile.objs
> @@ -3,3 +3,6 @@ obj-y += addr.o cputimer.o mips_int.o
>  obj-$(CONFIG_JAZZ) += mips_jazz.o
>  obj-$(CONFIG_FULONG) += mips_fulong2e.o
>  obj-y += gt64xxx_pci.o
> +obj-y += mips_pic32mz.o mips_pic32mx7.o
> +obj-y += pic32_load_hex.o pic32_sdcard.o pic32_spi.o pic32_uart.o pic32_gpio.o
> +obj-y += pic32_ethernet.o

Can we move mips-unrelated stuff to the appropriate dirs?
E.g. pic32_gpio.c can to go to hw/gpio.
Also please use separate patch for every peripheral controller (see Aurelien's comment).


> diff --git a/hw/mips/mips_pic32mx7.c b/hw/mips/mips_pic32mx7.c
> new file mode 100644
> index 0000000..1d8ffb5
> --- /dev/null
> +++ b/hw/mips/mips_pic32mx7.c
> @@ -0,0 +1,1652 @@
> +/*
> + * QEMU support for Microchip PIC32MX7 microcontroller.
> + *
> + * Copyright (c) 2015 Serge Vakulenko
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +/* Only 32-bit little endian mode supported. */
> +#include "config.h"
> +#if !defined TARGET_MIPS64 && !defined TARGET_WORDS_BIGENDIAN

Please don't use C preprocessor directive for conditional compilation of the whole file.
Use Makefile instead. See CONFIG_FULONG for example (fulong2e is mips64le-only).


-- 
Best regards,
  Antony Pavlov
Serge Vakulenko July 6, 2015, 4:18 a.m. UTC | #3
On Wed, Jul 1, 2015 at 6:41 AM, Aurelien Jarno <aurelien@aurel32.net> wrote:
> On 2015-06-30 21:12, Serge Vakulenko wrote:
>> Signed-off-by: Serge Vakulenko <serge.vakulenko@gmail.com>
>> ---
>>  hw/mips/Makefile.objs       |    3 +
>>  hw/mips/mips_pic32mx7.c     | 1652 +++++++++++++++++++++++++
>>  hw/mips/mips_pic32mz.c      | 2840 +++++++++++++++++++++++++++++++++++++++++++
>>  hw/mips/pic32_ethernet.c    |  557 +++++++++
>>  hw/mips/pic32_gpio.c        |   39 +
>>  hw/mips/pic32_load_hex.c    |  238 ++++
>>  hw/mips/pic32_peripherals.h |  210 ++++
>>  hw/mips/pic32_sdcard.c      |  428 +++++++
>>  hw/mips/pic32_spi.c         |  121 ++
>>  hw/mips/pic32_uart.c        |  228 ++++
>>  hw/mips/pic32mx.h           | 1290 ++++++++++++++++++++
>>  hw/mips/pic32mz.h           | 2093 +++++++++++++++++++++++++++++++
>>  12 files changed, 9699 insertions(+)
>>  create mode 100644 hw/mips/mips_pic32mx7.c
>>  create mode 100644 hw/mips/mips_pic32mz.c
>>  create mode 100644 hw/mips/pic32_ethernet.c
>>  create mode 100644 hw/mips/pic32_gpio.c
>>  create mode 100644 hw/mips/pic32_load_hex.c
>>  create mode 100644 hw/mips/pic32_peripherals.h
>>  create mode 100644 hw/mips/pic32_sdcard.c
>>  create mode 100644 hw/mips/pic32_spi.c
>>  create mode 100644 hw/mips/pic32_uart.c
>>  create mode 100644 hw/mips/pic32mx.h
>>  create mode 100644 hw/mips/pic32mz.h
>
> This patch is huge, and needs to be splitted to ease the review.

I'll prepare a new patch set, with every new file put into a separate
message. Other issues fixed as well.

> --
> Aurelien Jarno                          GPG: 4096R/1DDD8C9B
> aurelien@aurel32.net                 http://www.aurel32.net
Serge Vakulenko July 6, 2015, 4:27 a.m. UTC | #4
On Wed, Jul 1, 2015 at 10:56 PM, Antony Pavlov <antonynpavlov@gmail.com> wrote:
> On Tue, 30 Jun 2015 21:12:34 -0700
> Serge Vakulenko <serge.vakulenko@gmail.com> wrote:
>
>> Signed-off-by: Serge Vakulenko <serge.vakulenko@gmail.com>
>> ---
>>  hw/mips/Makefile.objs       |    3 +
>>  hw/mips/mips_pic32mx7.c     | 1652 +++++++++++++++++++++++++
>>  hw/mips/mips_pic32mz.c      | 2840 +++++++++++++++++++++++++++++++++++++++++++
>>  hw/mips/pic32_ethernet.c    |  557 +++++++++
>>  hw/mips/pic32_gpio.c        |   39 +
>>  hw/mips/pic32_load_hex.c    |  238 ++++
>>  hw/mips/pic32_peripherals.h |  210 ++++
>>  hw/mips/pic32_sdcard.c      |  428 +++++++
>>  hw/mips/pic32_spi.c         |  121 ++
>>  hw/mips/pic32_uart.c        |  228 ++++
>>  hw/mips/pic32mx.h           | 1290 ++++++++++++++++++++
>>  hw/mips/pic32mz.h           | 2093 +++++++++++++++++++++++++++++++
>>  12 files changed, 9699 insertions(+)
>>  create mode 100644 hw/mips/mips_pic32mx7.c
>>  create mode 100644 hw/mips/mips_pic32mz.c
>>  create mode 100644 hw/mips/pic32_ethernet.c
>>  create mode 100644 hw/mips/pic32_gpio.c
>>  create mode 100644 hw/mips/pic32_load_hex.c
>>  create mode 100644 hw/mips/pic32_peripherals.h
>>  create mode 100644 hw/mips/pic32_sdcard.c
>>  create mode 100644 hw/mips/pic32_spi.c
>>  create mode 100644 hw/mips/pic32_uart.c
>>  create mode 100644 hw/mips/pic32mx.h
>>  create mode 100644 hw/mips/pic32mz.h
>>
>> diff --git a/hw/mips/Makefile.objs b/hw/mips/Makefile.objs
>> index 9633f3a..dcbaec9 100644
>> --- a/hw/mips/Makefile.objs
>> +++ b/hw/mips/Makefile.objs
>> @@ -3,3 +3,6 @@ obj-y += addr.o cputimer.o mips_int.o
>>  obj-$(CONFIG_JAZZ) += mips_jazz.o
>>  obj-$(CONFIG_FULONG) += mips_fulong2e.o
>>  obj-y += gt64xxx_pci.o
>> +obj-y += mips_pic32mz.o mips_pic32mx7.o
>> +obj-y += pic32_load_hex.o pic32_sdcard.o pic32_spi.o pic32_uart.o pic32_gpio.o
>> +obj-y += pic32_ethernet.o
>
> Can we move mips-unrelated stuff to the appropriate dirs?
> E.g. pic32_gpio.c can to go to hw/gpio.

All these files are pic32-related. They depend on pic32_t data
structure declared in pic32_peripherals.h and register definitions in
pic32mx.h and pic32mz.h. I see no point to move them around.

> Also please use separate patch for every peripheral controller (see Aurelien's comment).

Agreed.

>> diff --git a/hw/mips/mips_pic32mx7.c b/hw/mips/mips_pic32mx7.c
>> new file mode 100644
>> index 0000000..1d8ffb5
>> --- /dev/null
>> +++ b/hw/mips/mips_pic32mx7.c
>> @@ -0,0 +1,1652 @@
>> +/*
>> + * QEMU support for Microchip PIC32MX7 microcontroller.
>> + *
>> + * Copyright (c) 2015 Serge Vakulenko
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining a copy
>> + * of this software and associated documentation files (the "Software"), to deal
>> + * in the Software without restriction, including without limitation the rights
>> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
>> + * copies of the Software, and to permit persons to whom the Software is
>> + * furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice shall be included in
>> + * all copies or substantial portions of the Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
>> + * THE SOFTWARE.
>> + */
>> +
>> +/* Only 32-bit little endian mode supported. */
>> +#include "config.h"
>> +#if !defined TARGET_MIPS64 && !defined TARGET_WORDS_BIGENDIAN
>
> Please don't use C preprocessor directive for conditional compilation of the whole file.
> Use Makefile instead. See CONFIG_FULONG for example (fulong2e is mips64le-only).

Makes sense.

Thanks,
--Serge

> --
> Best regards,
>   Antony Pavlov
Antony Pavlov July 6, 2015, 7:33 a.m. UTC | #5
On Sun, 5 Jul 2015 21:18:11 -0700
Serge Vakulenko <serge.vakulenko@gmail.com> wrote:

> On Wed, Jul 1, 2015 at 6:41 AM, Aurelien Jarno <aurelien@aurel32.net> wrote:
> > On 2015-06-30 21:12, Serge Vakulenko wrote:
> >> Signed-off-by: Serge Vakulenko <serge.vakulenko@gmail.com>
> >> ---
> >>  hw/mips/Makefile.objs       |    3 +
> >>  hw/mips/mips_pic32mx7.c     | 1652 +++++++++++++++++++++++++
> >>  hw/mips/mips_pic32mz.c      | 2840 +++++++++++++++++++++++++++++++++++++++++++
> >>  hw/mips/pic32_ethernet.c    |  557 +++++++++
> >>  hw/mips/pic32_gpio.c        |   39 +
> >>  hw/mips/pic32_load_hex.c    |  238 ++++
> >>  hw/mips/pic32_peripherals.h |  210 ++++
> >>  hw/mips/pic32_sdcard.c      |  428 +++++++
> >>  hw/mips/pic32_spi.c         |  121 ++
> >>  hw/mips/pic32_uart.c        |  228 ++++
> >>  hw/mips/pic32mx.h           | 1290 ++++++++++++++++++++
> >>  hw/mips/pic32mz.h           | 2093 +++++++++++++++++++++++++++++++
> >>  12 files changed, 9699 insertions(+)
> >>  create mode 100644 hw/mips/mips_pic32mx7.c
> >>  create mode 100644 hw/mips/mips_pic32mz.c
> >>  create mode 100644 hw/mips/pic32_ethernet.c
> >>  create mode 100644 hw/mips/pic32_gpio.c
> >>  create mode 100644 hw/mips/pic32_load_hex.c
> >>  create mode 100644 hw/mips/pic32_peripherals.h
> >>  create mode 100644 hw/mips/pic32_sdcard.c
> >>  create mode 100644 hw/mips/pic32_spi.c
> >>  create mode 100644 hw/mips/pic32_uart.c
> >>  create mode 100644 hw/mips/pic32mx.h
> >>  create mode 100644 hw/mips/pic32mz.h
> >
> > This patch is huge, and needs to be splitted to ease the review.
> 
> I'll prepare a new patch set, with every new file put into a separate
> message. Other issues fixed as well.

Putting every new file into a separate message is a nonsense.
Please separate __logical changes__ into a single patch.

-- 
Best regards,
  Antony Pavlov
Antony Pavlov July 6, 2015, 7:55 a.m. UTC | #6
On Sun, 5 Jul 2015 21:27:04 -0700
Serge Vakulenko <serge.vakulenko@gmail.com> wrote:

> On Wed, Jul 1, 2015 at 10:56 PM, Antony Pavlov <antonynpavlov@gmail.com> wrote:
> > On Tue, 30 Jun 2015 21:12:34 -0700
> > Serge Vakulenko <serge.vakulenko@gmail.com> wrote:
> >
> >> Signed-off-by: Serge Vakulenko <serge.vakulenko@gmail.com>
> >> ---
> >>  hw/mips/Makefile.objs       |    3 +
> >>  hw/mips/mips_pic32mx7.c     | 1652 +++++++++++++++++++++++++
> >>  hw/mips/mips_pic32mz.c      | 2840 +++++++++++++++++++++++++++++++++++++++++++
> >>  hw/mips/pic32_ethernet.c    |  557 +++++++++
> >>  hw/mips/pic32_gpio.c        |   39 +
> >>  hw/mips/pic32_load_hex.c    |  238 ++++
> >>  hw/mips/pic32_peripherals.h |  210 ++++
> >>  hw/mips/pic32_sdcard.c      |  428 +++++++
> >>  hw/mips/pic32_spi.c         |  121 ++
> >>  hw/mips/pic32_uart.c        |  228 ++++
> >>  hw/mips/pic32mx.h           | 1290 ++++++++++++++++++++
> >>  hw/mips/pic32mz.h           | 2093 +++++++++++++++++++++++++++++++
> >>  12 files changed, 9699 insertions(+)
> >>  create mode 100644 hw/mips/mips_pic32mx7.c
> >>  create mode 100644 hw/mips/mips_pic32mz.c
> >>  create mode 100644 hw/mips/pic32_ethernet.c
> >>  create mode 100644 hw/mips/pic32_gpio.c
> >>  create mode 100644 hw/mips/pic32_load_hex.c
> >>  create mode 100644 hw/mips/pic32_peripherals.h
> >>  create mode 100644 hw/mips/pic32_sdcard.c
> >>  create mode 100644 hw/mips/pic32_spi.c
> >>  create mode 100644 hw/mips/pic32_uart.c
> >>  create mode 100644 hw/mips/pic32mx.h
> >>  create mode 100644 hw/mips/pic32mz.h
> >>
> >> diff --git a/hw/mips/Makefile.objs b/hw/mips/Makefile.objs
> >> index 9633f3a..dcbaec9 100644
> >> --- a/hw/mips/Makefile.objs
> >> +++ b/hw/mips/Makefile.objs
> >> @@ -3,3 +3,6 @@ obj-y += addr.o cputimer.o mips_int.o
> >>  obj-$(CONFIG_JAZZ) += mips_jazz.o
> >>  obj-$(CONFIG_FULONG) += mips_fulong2e.o
> >>  obj-y += gt64xxx_pci.o
> >> +obj-y += mips_pic32mz.o mips_pic32mx7.o
> >> +obj-y += pic32_load_hex.o pic32_sdcard.o pic32_spi.o pic32_uart.o pic32_gpio.o
> >> +obj-y += pic32_ethernet.o
> >
> > Can we move mips-unrelated stuff to the appropriate dirs?
> > E.g. pic32_gpio.c can to go to hw/gpio.
> 
> All these files are pic32-related. They depend on pic32_t data
> structure declared in pic32_peripherals.h and register definitions in
> pic32mx.h and pic32mz.h. I see no point to move them around.

But why hw/gpio/pic32_gpio.c can't include pic32_peripherals.h?
You can see that mainline qemu.git/hw/mips/ does not contain any header file,
so just put your header files into the proper dir (I suppose qemu.git/include/hw/mips).


> > Also please use separate patch for every peripheral controller (see Aurelien's comment).
> 
> Agreed.
> 
> >> diff --git a/hw/mips/mips_pic32mx7.c b/hw/mips/mips_pic32mx7.c
> >> new file mode 100644
> >> index 0000000..1d8ffb5
> >> --- /dev/null
> >> +++ b/hw/mips/mips_pic32mx7.c
> >> @@ -0,0 +1,1652 @@
> >> +/*
> >> + * QEMU support for Microchip PIC32MX7 microcontroller.
> >> + *
> >> + * Copyright (c) 2015 Serge Vakulenko
> >> + *
> >> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> >> + * of this software and associated documentation files (the "Software"), to deal
> >> + * in the Software without restriction, including without limitation the rights
> >> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> >> + * copies of the Software, and to permit persons to whom the Software is
> >> + * furnished to do so, subject to the following conditions:
> >> + *
> >> + * The above copyright notice and this permission notice shall be included in
> >> + * all copies or substantial portions of the Software.
> >> + *
> >> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> >> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> >> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> >> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> >> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> >> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> >> + * THE SOFTWARE.
> >> + */
> >> +
> >> +/* Only 32-bit little endian mode supported. */
> >> +#include "config.h"
> >> +#if !defined TARGET_MIPS64 && !defined TARGET_WORDS_BIGENDIAN
> >
> > Please don't use C preprocessor directive for conditional compilation of the whole file.
> > Use Makefile instead. See CONFIG_FULONG for example (fulong2e is mips64le-only).
> 
> Makes sense.
> 
> Thanks,
> --Serge
> 
> > --
> > Best regards,
> >   Antony Pavlov
Serge Vakulenko July 6, 2015, 6:58 p.m. UTC | #7
On Mon, Jul 6, 2015 at 12:33 AM, Antony Pavlov <antonynpavlov@gmail.com> wrote:
> On Sun, 5 Jul 2015 21:18:11 -0700
> Serge Vakulenko <serge.vakulenko@gmail.com> wrote:
>
>> On Wed, Jul 1, 2015 at 6:41 AM, Aurelien Jarno <aurelien@aurel32.net> wrote:
>> > On 2015-06-30 21:12, Serge Vakulenko wrote:
>> >> Signed-off-by: Serge Vakulenko <serge.vakulenko@gmail.com>
>> >> ---
>> >>  hw/mips/Makefile.objs       |    3 +
>> >>  hw/mips/mips_pic32mx7.c     | 1652 +++++++++++++++++++++++++
>> >>  hw/mips/mips_pic32mz.c      | 2840 +++++++++++++++++++++++++++++++++++++++++++
>> >>  hw/mips/pic32_ethernet.c    |  557 +++++++++
>> >>  hw/mips/pic32_gpio.c        |   39 +
>> >>  hw/mips/pic32_load_hex.c    |  238 ++++
>> >>  hw/mips/pic32_peripherals.h |  210 ++++
>> >>  hw/mips/pic32_sdcard.c      |  428 +++++++
>> >>  hw/mips/pic32_spi.c         |  121 ++
>> >>  hw/mips/pic32_uart.c        |  228 ++++
>> >>  hw/mips/pic32mx.h           | 1290 ++++++++++++++++++++
>> >>  hw/mips/pic32mz.h           | 2093 +++++++++++++++++++++++++++++++
>> >>  12 files changed, 9699 insertions(+)
>> >>  create mode 100644 hw/mips/mips_pic32mx7.c
>> >>  create mode 100644 hw/mips/mips_pic32mz.c
>> >>  create mode 100644 hw/mips/pic32_ethernet.c
>> >>  create mode 100644 hw/mips/pic32_gpio.c
>> >>  create mode 100644 hw/mips/pic32_load_hex.c
>> >>  create mode 100644 hw/mips/pic32_peripherals.h
>> >>  create mode 100644 hw/mips/pic32_sdcard.c
>> >>  create mode 100644 hw/mips/pic32_spi.c
>> >>  create mode 100644 hw/mips/pic32_uart.c
>> >>  create mode 100644 hw/mips/pic32mx.h
>> >>  create mode 100644 hw/mips/pic32mz.h
>> >
>> > This patch is huge, and needs to be splitted to ease the review.
>>
>> I'll prepare a new patch set, with every new file put into a separate
>> message. Other issues fixed as well.
>
> Putting every new file into a separate message is a nonsense.
> Please separate __logical changes__ into a single patch.

Aurelien Jarno asked to split this patch to ease the review.

> --
> Best regards,
>   Antony Pavlov
Peter Crosthwaite July 6, 2015, 9:43 p.m. UTC | #8
On Mon, Jul 6, 2015 at 11:58 AM, Serge Vakulenko
<serge.vakulenko@gmail.com> wrote:
> On Mon, Jul 6, 2015 at 12:33 AM, Antony Pavlov <antonynpavlov@gmail.com> wrote:
>> On Sun, 5 Jul 2015 21:18:11 -0700
>> Serge Vakulenko <serge.vakulenko@gmail.com> wrote:
>>
>>> On Wed, Jul 1, 2015 at 6:41 AM, Aurelien Jarno <aurelien@aurel32.net> wrote:
>>> > On 2015-06-30 21:12, Serge Vakulenko wrote:
>>> >> Signed-off-by: Serge Vakulenko <serge.vakulenko@gmail.com>
>>> >> ---
>>> >>  hw/mips/Makefile.objs       |    3 +
>>> >>  hw/mips/mips_pic32mx7.c     | 1652 +++++++++++++++++++++++++
>>> >>  hw/mips/mips_pic32mz.c      | 2840 +++++++++++++++++++++++++++++++++++++++++++
>>> >>  hw/mips/pic32_ethernet.c    |  557 +++++++++
>>> >>  hw/mips/pic32_gpio.c        |   39 +
>>> >>  hw/mips/pic32_load_hex.c    |  238 ++++
>>> >>  hw/mips/pic32_peripherals.h |  210 ++++
>>> >>  hw/mips/pic32_sdcard.c      |  428 +++++++
>>> >>  hw/mips/pic32_spi.c         |  121 ++
>>> >>  hw/mips/pic32_uart.c        |  228 ++++
>>> >>  hw/mips/pic32mx.h           | 1290 ++++++++++++++++++++
>>> >>  hw/mips/pic32mz.h           | 2093 +++++++++++++++++++++++++++++++
>>> >>  12 files changed, 9699 insertions(+)
>>> >>  create mode 100644 hw/mips/mips_pic32mx7.c
>>> >>  create mode 100644 hw/mips/mips_pic32mz.c
>>> >>  create mode 100644 hw/mips/pic32_ethernet.c
>>> >>  create mode 100644 hw/mips/pic32_gpio.c
>>> >>  create mode 100644 hw/mips/pic32_load_hex.c
>>> >>  create mode 100644 hw/mips/pic32_peripherals.h
>>> >>  create mode 100644 hw/mips/pic32_sdcard.c
>>> >>  create mode 100644 hw/mips/pic32_spi.c
>>> >>  create mode 100644 hw/mips/pic32_uart.c
>>> >>  create mode 100644 hw/mips/pic32mx.h
>>> >>  create mode 100644 hw/mips/pic32mz.h
>>> >
>>> > This patch is huge, and needs to be splitted to ease the review.
>>>
>>> I'll prepare a new patch set, with every new file put into a separate
>>> message. Other issues fixed as well.
>>
>> Putting every new file into a separate message is a nonsense.
>> Please separate __logical changes__ into a single patch.
>
> Aurelien Jarno asked to split this patch to ease the review.
>

There are better ways to split the patch other than straight per-file
though. For example, header patches (e.g. for your structs) should go
with their accompanying C code changes.

git add -p is the interactive utility for selecting specific changes
to be included in a commit.

Regards,
Peter

>> --
>> Best regards,
>>   Antony Pavlov
>
Antony Pavlov July 7, 2015, 7:30 a.m. UTC | #9
On Mon, 6 Jul 2015 11:58:54 -0700
Serge Vakulenko <serge.vakulenko@gmail.com> wrote:

> On Mon, Jul 6, 2015 at 12:33 AM, Antony Pavlov <antonynpavlov@gmail.com> wrote:
> > On Sun, 5 Jul 2015 21:18:11 -0700
> > Serge Vakulenko <serge.vakulenko@gmail.com> wrote:
> >
> >> On Wed, Jul 1, 2015 at 6:41 AM, Aurelien Jarno <aurelien@aurel32.net> wrote:
> >> > On 2015-06-30 21:12, Serge Vakulenko wrote:
> >> >> Signed-off-by: Serge Vakulenko <serge.vakulenko@gmail.com>
> >> >> ---
> >> >>  hw/mips/Makefile.objs       |    3 +
> >> >>  hw/mips/mips_pic32mx7.c     | 1652 +++++++++++++++++++++++++
> >> >>  hw/mips/mips_pic32mz.c      | 2840 +++++++++++++++++++++++++++++++++++++++++++
> >> >>  hw/mips/pic32_ethernet.c    |  557 +++++++++
> >> >>  hw/mips/pic32_gpio.c        |   39 +
> >> >>  hw/mips/pic32_load_hex.c    |  238 ++++
> >> >>  hw/mips/pic32_peripherals.h |  210 ++++
> >> >>  hw/mips/pic32_sdcard.c      |  428 +++++++
> >> >>  hw/mips/pic32_spi.c         |  121 ++
> >> >>  hw/mips/pic32_uart.c        |  228 ++++
> >> >>  hw/mips/pic32mx.h           | 1290 ++++++++++++++++++++
> >> >>  hw/mips/pic32mz.h           | 2093 +++++++++++++++++++++++++++++++
> >> >>  12 files changed, 9699 insertions(+)
> >> >>  create mode 100644 hw/mips/mips_pic32mx7.c
> >> >>  create mode 100644 hw/mips/mips_pic32mz.c
> >> >>  create mode 100644 hw/mips/pic32_ethernet.c
> >> >>  create mode 100644 hw/mips/pic32_gpio.c
> >> >>  create mode 100644 hw/mips/pic32_load_hex.c
> >> >>  create mode 100644 hw/mips/pic32_peripherals.h
> >> >>  create mode 100644 hw/mips/pic32_sdcard.c
> >> >>  create mode 100644 hw/mips/pic32_spi.c
> >> >>  create mode 100644 hw/mips/pic32_uart.c
> >> >>  create mode 100644 hw/mips/pic32mx.h
> >> >>  create mode 100644 hw/mips/pic32mz.h
> >> >
> >> > This patch is huge, and needs to be splitted to ease the review.
> >>
> >> I'll prepare a new patch set, with every new file put into a separate
> >> message. Other issues fixed as well.
> >
> > Putting every new file into a separate message is a nonsense.
> > Please separate __logical changes__ into a single patch.
> 
> Aurelien Jarno asked to split this patch to ease the review.

IMHO he meant something very different.

Please reread the qemu submitting patch manual carefully
(see http://wiki.qemu.org/Contribute/SubmitAPatch).

Here is a quote:

  Split up longer patches into a patch series of logical code changes.
  Each change should compile and execute successfully. For instance,
  don't add a file to the makefile in patch one and then add the file itself
  in patch two. (This rule is here so that people can later use tools
  like git bisect without hitting points in the commit history
  where QEMU doesn't work for reasons unrelated to the bug they're chasing.)

Also please reread this Peter's comment very very carefully:
  
   http://lists.nongnu.org/archive/html/qemu-devel/2015-07/msg01430.html

Peter asks you to rework your device support code: every device should be self-contained.
E.g. for UART support code this means that:

   0. Object model is used. Your UART code implements operation of one UART instance.
      private structure is used for storing UART instance's current state.
      The SoC code (or even board code) creates as many UART instances as it needs.

      Also please see this Aurilien's comment: http://lists.nongnu.org/archive/html/qemu-devel/2015-07/msg01242.html

   1. UART C code go to qemu.git/hw/char/;

   2. externally visible UART stuff (header file) go to qemu.git/include/hw/char/;

      Pay attention that there is no need to put all UART related macro into header file.
      If nobody outside your UART C code use these macros then you can keep their definition in the C code.

   3. UART C code compilation has to be enabled only for mips-softmmu target.
      So make your UART C code compilation dependendent on a Makefile option,
      enable this option only in qemu.git/default-configs/mips-softmmu.mak.

   4. UART support have to be added in a separate patch. So this patch have to contain changes in these files:

        default-configs/mips-softmmu.mak
        hw/char/Makefile.objs
        hw/char/pic32_uart.c
        include/hw/char/pic32_uart.h
      
      This UART support patch has to be submitted __before__ a patch with SoC/board code that use UART.


As Peter suggests please use 'Netduino 2 Machine Model' patchseries as a model,
  see http://lists.gnu.org/archive/html/qemu-devel/2015-02/msg03398.html

-- 
Best regards,
  Antony Pavlov
Aurelien Jarno July 7, 2015, 2:08 p.m. UTC | #10
On 2015-07-07 10:30, Antony Pavlov wrote:
> On Mon, 6 Jul 2015 11:58:54 -0700
> Serge Vakulenko <serge.vakulenko@gmail.com> wrote:
> 
> > On Mon, Jul 6, 2015 at 12:33 AM, Antony Pavlov <antonynpavlov@gmail.com> wrote:
> > > On Sun, 5 Jul 2015 21:18:11 -0700
> > > Serge Vakulenko <serge.vakulenko@gmail.com> wrote:
> > >
> > >> On Wed, Jul 1, 2015 at 6:41 AM, Aurelien Jarno <aurelien@aurel32.net> wrote:
> > >> > On 2015-06-30 21:12, Serge Vakulenko wrote:
> > >> >> Signed-off-by: Serge Vakulenko <serge.vakulenko@gmail.com>
> > >> >> ---
> > >> >>  hw/mips/Makefile.objs       |    3 +
> > >> >>  hw/mips/mips_pic32mx7.c     | 1652 +++++++++++++++++++++++++
> > >> >>  hw/mips/mips_pic32mz.c      | 2840 +++++++++++++++++++++++++++++++++++++++++++
> > >> >>  hw/mips/pic32_ethernet.c    |  557 +++++++++
> > >> >>  hw/mips/pic32_gpio.c        |   39 +
> > >> >>  hw/mips/pic32_load_hex.c    |  238 ++++
> > >> >>  hw/mips/pic32_peripherals.h |  210 ++++
> > >> >>  hw/mips/pic32_sdcard.c      |  428 +++++++
> > >> >>  hw/mips/pic32_spi.c         |  121 ++
> > >> >>  hw/mips/pic32_uart.c        |  228 ++++
> > >> >>  hw/mips/pic32mx.h           | 1290 ++++++++++++++++++++
> > >> >>  hw/mips/pic32mz.h           | 2093 +++++++++++++++++++++++++++++++
> > >> >>  12 files changed, 9699 insertions(+)
> > >> >>  create mode 100644 hw/mips/mips_pic32mx7.c
> > >> >>  create mode 100644 hw/mips/mips_pic32mz.c
> > >> >>  create mode 100644 hw/mips/pic32_ethernet.c
> > >> >>  create mode 100644 hw/mips/pic32_gpio.c
> > >> >>  create mode 100644 hw/mips/pic32_load_hex.c
> > >> >>  create mode 100644 hw/mips/pic32_peripherals.h
> > >> >>  create mode 100644 hw/mips/pic32_sdcard.c
> > >> >>  create mode 100644 hw/mips/pic32_spi.c
> > >> >>  create mode 100644 hw/mips/pic32_uart.c
> > >> >>  create mode 100644 hw/mips/pic32mx.h
> > >> >>  create mode 100644 hw/mips/pic32mz.h
> > >> >
> > >> > This patch is huge, and needs to be splitted to ease the review.
> > >>
> > >> I'll prepare a new patch set, with every new file put into a separate
> > >> message. Other issues fixed as well.
> > >
> > > Putting every new file into a separate message is a nonsense.
> > > Please separate __logical changes__ into a single patch.
> > 
> > Aurelien Jarno asked to split this patch to ease the review.
> 
> IMHO he meant something very different.

I confirm I wanted basically a changeset progressively adding devices,
like one patch per devices.

> Please reread the qemu submitting patch manual carefully
> (see http://wiki.qemu.org/Contribute/SubmitAPatch).
> 
> Here is a quote:
> 
>   Split up longer patches into a patch series of logical code changes.
>   Each change should compile and execute successfully. For instance,
>   don't add a file to the makefile in patch one and then add the file itself
>   in patch two. (This rule is here so that people can later use tools
>   like git bisect without hitting points in the commit history
>   where QEMU doesn't work for reasons unrelated to the bug they're chasing.)
> 
> Also please reread this Peter's comment very very carefully:
>   
>    http://lists.nongnu.org/archive/html/qemu-devel/2015-07/msg01430.html
> 
> Peter asks you to rework your device support code: every device should be self-contained.
> E.g. for UART support code this means that:
> 
>    0. Object model is used. Your UART code implements operation of one UART instance.
>       private structure is used for storing UART instance's current state.
>       The SoC code (or even board code) creates as many UART instances as it needs.
> 
>       Also please see this Aurilien's comment: http://lists.nongnu.org/archive/html/qemu-devel/2015-07/msg01242.html
> 
>    1. UART C code go to qemu.git/hw/char/;
> 
>    2. externally visible UART stuff (header file) go to qemu.git/include/hw/char/;
> 
>       Pay attention that there is no need to put all UART related macro into header file.
>       If nobody outside your UART C code use these macros then you can keep their definition in the C code.
> 
>    3. UART C code compilation has to be enabled only for mips-softmmu target.
>       So make your UART C code compilation dependendent on a Makefile option,
>       enable this option only in qemu.git/default-configs/mips-softmmu.mak.
> 
>    4. UART support have to be added in a separate patch. So this patch have to contain changes in these files:
> 
>         default-configs/mips-softmmu.mak
>         hw/char/Makefile.objs
>         hw/char/pic32_uart.c
>         include/hw/char/pic32_uart.h
>       
>       This UART support patch has to be submitted __before__ a patch with SoC/board code that use UART.
> 
> 
> As Peter suggests please use 'Netduino 2 Machine Model' patchseries as a model,
>   see http://lists.gnu.org/archive/html/qemu-devel/2015-02/msg03398.html

Thanks for the detailed guidelines, it's quite useful.

Aurelien
diff mbox

Patch

diff --git a/hw/mips/Makefile.objs b/hw/mips/Makefile.objs
index 9633f3a..dcbaec9 100644
--- a/hw/mips/Makefile.objs
+++ b/hw/mips/Makefile.objs
@@ -3,3 +3,6 @@  obj-y += addr.o cputimer.o mips_int.o
 obj-$(CONFIG_JAZZ) += mips_jazz.o
 obj-$(CONFIG_FULONG) += mips_fulong2e.o
 obj-y += gt64xxx_pci.o
+obj-y += mips_pic32mz.o mips_pic32mx7.o
+obj-y += pic32_load_hex.o pic32_sdcard.o pic32_spi.o pic32_uart.o pic32_gpio.o
+obj-y += pic32_ethernet.o
diff --git a/hw/mips/mips_pic32mx7.c b/hw/mips/mips_pic32mx7.c
new file mode 100644
index 0000000..1d8ffb5
--- /dev/null
+++ b/hw/mips/mips_pic32mx7.c
@@ -0,0 +1,1652 @@ 
+/*
+ * QEMU support for Microchip PIC32MX7 microcontroller.
+ *
+ * Copyright (c) 2015 Serge Vakulenko
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/* Only 32-bit little endian mode supported. */
+#include "config.h"
+#if !defined TARGET_MIPS64 && !defined TARGET_WORDS_BIGENDIAN
+
+#include "hw/i386/pc.h"
+#include "hw/char/serial.h"
+#include "hw/mips/cpudevs.h"
+#include "sysemu/char.h"
+#include "hw/loader.h"
+#include "qemu/error-report.h"
+#include "hw/empty_slot.h"
+#include <termios.h>
+
+#define PIC32MX7
+#include "pic32mx.h"
+#include "pic32_peripherals.h"
+
+/* Hardware addresses */
+#define PROGRAM_FLASH_START 0x1d000000
+#define BOOT_FLASH_START    0x1fc00000
+#define DATA_MEM_START      0x00000000
+#define IO_MEM_START        0x1f800000
+
+#define PROGRAM_FLASH_SIZE  (512*1024)          /* 512 kbytes */
+#define BOOT_FLASH_SIZE     (12*1024)           /* 12 kbytes */
+#define DATA_MEM_SIZE       (128*1024)          /* 128 kbytes */
+#define USER_MEM_START      0xbf000000
+
+#define TYPE_MIPS_PIC32     "mips-pic32mx7"
+
+/*
+ * Board variants.
+ */
+enum {
+    BOARD_MAX32,            /* chipKIT Max32 board */
+    BOARD_MAXIMITE,         /* Geoff's Maximite board */
+    BOARD_EXPLORER16,       /* Microchip Explorer-16 board */
+};
+
+static const char *board_name[] = {
+    "chipKIT Max32",
+    "Geoff's Maximite Computer",
+    "Microchip Explorer16",
+};
+
+/*
+ * Pointers to Flash memory contents.
+ */
+static char *prog_ptr;
+static char *boot_ptr;
+
+#define BOOTMEM(addr) ((uint32_t *) boot_ptr)[(addr & 0xffff) >> 2]
+
+/*
+ * TODO: add option to enable tracing.
+ */
+#define TRACE   0
+
+/*
+ * PIC32MX7 specific table:
+ * translate IRQ number to interrupt vector.
+ */
+static const int irq_to_vector[] = {
+    PIC32_VECT_CT,          /* 0  - Core Timer Interrupt */
+    PIC32_VECT_CS0,         /* 1  - Core Software Interrupt 0 */
+    PIC32_VECT_CS1,         /* 2  - Core Software Interrupt 1 */
+    PIC32_VECT_INT0,        /* 3  - External Interrupt 0 */
+    PIC32_VECT_T1,          /* 4  - Timer1 */
+    PIC32_VECT_IC1,         /* 5  - Input Capture 1 */
+    PIC32_VECT_OC1,         /* 6  - Output Compare 1 */
+    PIC32_VECT_INT1,        /* 7  - External Interrupt 1 */
+    PIC32_VECT_T2,          /* 8  - Timer2 */
+    PIC32_VECT_IC2,         /* 9  - Input Capture 2 */
+    PIC32_VECT_OC2,         /* 10 - Output Compare 2 */
+    PIC32_VECT_INT2,        /* 11 - External Interrupt 2 */
+    PIC32_VECT_T3,          /* 12 - Timer3 */
+    PIC32_VECT_IC3,         /* 13 - Input Capture 3 */
+    PIC32_VECT_OC3,         /* 14 - Output Compare 3 */
+    PIC32_VECT_INT3,        /* 15 - External Interrupt 3 */
+    PIC32_VECT_T4,          /* 16 - Timer4 */
+    PIC32_VECT_IC4,         /* 17 - Input Capture 4 */
+    PIC32_VECT_OC4,         /* 18 - Output Compare 4 */
+    PIC32_VECT_INT4,        /* 19 - External Interrupt 4 */
+    PIC32_VECT_T5,          /* 20 - Timer5 */
+    PIC32_VECT_IC5,         /* 21 - Input Capture 5 */
+    PIC32_VECT_OC5,         /* 22 - Output Compare 5 */
+    PIC32_VECT_SPI1,        /* 23 - SPI1 Fault */
+    PIC32_VECT_SPI1,        /* 24 - SPI1 Transfer Done */
+    PIC32_VECT_SPI1,        /* 25 - SPI1 Receive Done */
+
+    PIC32_VECT_U1     |     /* 26 - UART1 Error */
+    PIC32_VECT_SPI3   |     /* 26 - SPI3 Fault */
+    PIC32_VECT_I2C3,        /* 26 - I2C3 Bus Collision Event */
+
+    PIC32_VECT_U1     |     /* 27 - UART1 Receiver */
+    PIC32_VECT_SPI3   |     /* 27 - SPI3 Transfer Done */
+    PIC32_VECT_I2C3,        /* 27 - I2C3 Slave Event */
+
+    PIC32_VECT_U1     |     /* 28 - UART1 Transmitter */
+    PIC32_VECT_SPI3   |     /* 28 - SPI3 Receive Done */
+    PIC32_VECT_I2C3,        /* 28 - I2C3 Master Event */
+
+    PIC32_VECT_I2C1,        /* 29 - I2C1 Bus Collision Event */
+    PIC32_VECT_I2C1,        /* 30 - I2C1 Slave Event */
+    PIC32_VECT_I2C1,        /* 31 - I2C1 Master Event */
+    PIC32_VECT_CN,          /* 32 - Input Change Interrupt */
+    PIC32_VECT_AD1,         /* 33 - ADC1 Convert Done */
+    PIC32_VECT_PMP,         /* 34 - Parallel Master Port */
+    PIC32_VECT_CMP1,        /* 35 - Comparator Interrupt */
+    PIC32_VECT_CMP2,        /* 36 - Comparator Interrupt */
+
+    PIC32_VECT_U3     |     /* 37 - UART3 Error */
+    PIC32_VECT_SPI2   |     /* 37 - SPI2 Fault */
+    PIC32_VECT_I2C4,        /* 37 - I2C4 Bus Collision Event */
+
+    PIC32_VECT_U3     |     /* 38 - UART3 Receiver */
+    PIC32_VECT_SPI2   |     /* 38 - SPI2 Transfer Done */
+    PIC32_VECT_I2C4,        /* 38 - I2C4 Slave Event */
+
+    PIC32_VECT_U3     |     /* 39 - UART3 Transmitter */
+    PIC32_VECT_SPI2   |     /* 39 - SPI2 Receive Done */
+    PIC32_VECT_I2C4,        /* 39 - I2C4 Master Event */
+
+    PIC32_VECT_U2     |     /* 40 - UART2 Error */
+    PIC32_VECT_SPI4   |     /* 40 - SPI4 Fault */
+    PIC32_VECT_I2C5,        /* 40 - I2C5 Bus Collision Event */
+
+    PIC32_VECT_U2     |     /* 41 - UART2 Receiver */
+    PIC32_VECT_SPI4   |     /* 41 - SPI4 Transfer Done */
+    PIC32_VECT_I2C5,        /* 41 - I2C5 Slave Event */
+
+    PIC32_VECT_U2     |     /* 42 - UART2 Transmitter */
+    PIC32_VECT_SPI4   |     /* 42 - SPI4 Receive Done */
+    PIC32_VECT_I2C5,        /* 42 - I2C5 Master Event */
+
+    PIC32_VECT_I2C2,        /* 43 - I2C2 Bus Collision Event */
+    PIC32_VECT_I2C2,        /* 44 - I2C2 Slave Event */
+    PIC32_VECT_I2C2,        /* 45 - I2C2 Master Event */
+    PIC32_VECT_FSCM,        /* 46 - Fail-Safe Clock Monitor */
+    PIC32_VECT_RTCC,        /* 47 - Real-Time Clock and Calendar */
+    PIC32_VECT_DMA0,        /* 48 - DMA Channel 0 */
+    PIC32_VECT_DMA1,        /* 49 - DMA Channel 1 */
+    PIC32_VECT_DMA2,        /* 50 - DMA Channel 2 */
+    PIC32_VECT_DMA3,        /* 51 - DMA Channel 3 */
+    PIC32_VECT_DMA4,        /* 52 - DMA Channel 4 */
+    PIC32_VECT_DMA5,        /* 53 - DMA Channel 5 */
+    PIC32_VECT_DMA6,        /* 54 - DMA Channel 6 */
+    PIC32_VECT_DMA7,        /* 55 - DMA Channel 7 */
+    PIC32_VECT_FCE,         /* 56 - Flash Control Event */
+    PIC32_VECT_USB,         /* 57 - USB */
+    PIC32_VECT_CAN1,        /* 58 - Control Area Network 1 */
+    PIC32_VECT_CAN2,        /* 59 - Control Area Network 2 */
+    PIC32_VECT_ETH,         /* 60 - Ethernet Interrupt */
+    PIC32_VECT_IC1,         /* 61 - Input Capture 1 Error */
+    PIC32_VECT_IC2,         /* 62 - Input Capture 2 Error */
+    PIC32_VECT_IC3,         /* 63 - Input Capture 3 Error */
+    PIC32_VECT_IC4,         /* 64 - Input Capture 4 Error */
+    PIC32_VECT_IC5,         /* 65 - Input Capture 5 Error */
+    PIC32_VECT_PMP,         /* 66 - Parallel Master Port Error */
+    PIC32_VECT_U4,          /* 67 - UART4 Error */
+    PIC32_VECT_U4,          /* 68 - UART4 Receiver */
+    PIC32_VECT_U4,          /* 69 - UART4 Transmitter */
+    PIC32_VECT_U6,          /* 70 - UART6 Error */
+    PIC32_VECT_U6,          /* 71 - UART6 Receiver */
+    PIC32_VECT_U6,          /* 72 - UART6 Transmitter */
+    PIC32_VECT_U5,          /* 73 - UART5 Error */
+    PIC32_VECT_U5,          /* 74 - UART5 Receiver */
+    PIC32_VECT_U5,          /* 75 - UART5 Transmitter */
+};
+
+static void update_irq_status(pic32_t *s)
+{
+    /* Assume no interrupts pending. */
+    int cause_ripl = 0;
+    int vector = 0;
+    CPUMIPSState *env = &s->cpu->env;
+    int current_ripl = (env->CP0_Cause >> (CP0Ca_IP + 2)) & 0x3f;
+
+    VALUE(INTSTAT) = 0;
+
+    if ((VALUE(IFS0) & VALUE(IEC0)) ||
+        (VALUE(IFS1) & VALUE(IEC1)) ||
+        (VALUE(IFS2) & VALUE(IEC2)))
+    {
+        /* Find the most prioritive pending interrupt,
+         * it's vector and level. */
+        int irq;
+        for (irq = 0; irq < sizeof(irq_to_vector)/sizeof(int); irq++) {
+            int n = irq >> 5;
+
+            if (((VALUE(IFS(n)) & VALUE(IEC(n))) >> (irq & 31)) & 1) {
+                /* Interrupt is pending. */
+                int v = irq_to_vector[irq];
+                if (v < 0) {
+                    continue;
+                }
+
+                int level = VALUE(IPC(v >> 2));
+                level >>= 2 + (v & 3) * 8;
+                level &= 7;
+                if (level > cause_ripl) {
+                    vector = v;
+                    cause_ripl = level;
+                }
+            }
+        }
+        VALUE(INTSTAT) = vector | (cause_ripl << 8);
+    }
+
+    if (cause_ripl == current_ripl) {
+        return;
+    }
+
+    if (TRACE) {
+        fprintf(qemu_logfile, "--- Priority level Cause.RIPL = %u\n",
+            cause_ripl);
+    }
+
+    /*
+     * Modify Cause.RIPL field and take EIC interrupt.
+     */
+    env->CP0_Cause &= ~(0x3f << (CP0Ca_IP + 2));
+    env->CP0_Cause |= cause_ripl << (CP0Ca_IP + 2);
+    cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_HARD);
+}
+
+/*
+ * Set interrupt flag status
+ */
+static void irq_raise(pic32_t *s, int irq)
+{
+    if (VALUE(IFS(irq >> 5)) & (1 << (irq & 31))) {
+        return;
+    }
+
+    VALUE(IFS(irq >> 5)) |= 1 << (irq & 31);
+    update_irq_status(s);
+}
+
+/*
+ * Clear interrupt flag status
+ */
+static void irq_clear(pic32_t *s, int irq)
+{
+    if (!(VALUE(IFS(irq >> 5)) & (1 << (irq & 31)))) {
+        return;
+    }
+
+    VALUE(IFS(irq >> 5)) &= ~(1 << (irq & 31));
+    update_irq_status(s);
+}
+
+/*
+ * Timer interrupt.
+ */
+static void pic32_timer_irq(CPUMIPSState *env, int raise)
+{
+    pic32_t *s = env->eic_context;
+
+    if (raise) {
+        if (TRACE) {
+            fprintf(qemu_logfile, "--- %08x: Timer interrupt\n",
+                env->active_tc.PC);
+        }
+        irq_raise(s, 0);
+    } else {
+        if (TRACE) {
+            fprintf(qemu_logfile, "--- Clear timer interrupt\n");
+        }
+        irq_clear(s, 0);
+    }
+}
+
+/*
+ * Software interrupt.
+ */
+static void pic32_soft_irq(CPUMIPSState *env, int num)
+{
+    pic32_t *s = env->eic_context;
+
+    if (TRACE) {
+        fprintf(qemu_logfile, "--- %08x: Soft interrupt %u\n",
+            env->active_tc.PC, num);
+    }
+    irq_raise(s, num + 1);
+}
+
+/*
+ * Perform an assign/clear/set/invert operation.
+ */
+static inline unsigned write_op(int a, int b, int op)
+{
+    switch (op & 0xc) {
+    case 0x0:                   /* Assign */
+        a = b;
+        break;
+    case 0x4:                   /* Clear */
+        a &= ~b;
+        break;
+    case 0x8:                   /* Set */
+        a |= b;
+        break;
+    case 0xc:                   /* Invert */
+        a ^= b;
+        break;
+    }
+    return a;
+}
+
+static void io_reset(pic32_t *s)
+{
+    int i;
+
+    /*
+     * Bus matrix control registers.
+     */
+    VALUE(BMXCON)    = 0x001f0041;  /* Bus Matrix Control */
+    VALUE(BMXDKPBA)  = 0;           /* Data RAM kernel program base */
+    VALUE(BMXDUDBA)  = 0;           /* Data RAM user data base address */
+    VALUE(BMXDUPBA)  = 0;           /* Data RAM user program base */
+    VALUE(BMXPUPBA)  = 0;           /* Program Flash user program base */
+    VALUE(BMXDRMSZ)  = 128 * 1024;  /* Data RAM memory size */
+    VALUE(BMXPFMSZ)  = 512 * 1024;  /* Program Flash memory size */
+    VALUE(BMXBOOTSZ) = 12 * 1024;   /* Boot Flash size */
+
+    /*
+     * Prefetch controller.
+     */
+    VALUE(CHECON) = 0x00000007;
+
+    /*
+     * System controller.
+     */
+    VALUE(OSCTUN) = 0;
+    VALUE(DDPCON) = 0;
+    VALUE(SYSKEY) = 0;
+    VALUE(RCON)   = 0;
+    VALUE(RSWRST) = 0;
+    s->syskey_unlock = 0;
+
+    /*
+     * Analog to digital converter.
+     */
+    VALUE(AD1CON1) = 0;             /* Control register 1 */
+    VALUE(AD1CON2) = 0;             /* Control register 2 */
+    VALUE(AD1CON3) = 0;             /* Control register 3 */
+    VALUE(AD1CHS)  = 0;             /* Channel select */
+    VALUE(AD1CSSL) = 0;             /* Input scan selection */
+    VALUE(AD1PCFG) = 0;             /* Port configuration */
+
+    /*
+     * General purpose IO signals.
+     * All pins are inputs, high, open drains and pullups disabled.
+     * No interrupts on change.
+     */
+    VALUE(TRISA) = 0xFFFF;          /* Port A: mask of inputs */
+    VALUE(PORTA) = 0xFFFF;          /* Port A: read inputs, write outputs */
+    VALUE(LATA)  = 0xFFFF;          /* Port A: read/write outputs */
+    VALUE(ODCA)  = 0;               /* Port A: open drain configuration */
+    VALUE(TRISB) = 0xFFFF;          /* Port B: mask of inputs */
+    VALUE(PORTB) = 0xFFFF;          /* Port B: read inputs, write outputs */
+    VALUE(LATB)  = 0xFFFF;          /* Port B: read/write outputs */
+    VALUE(ODCB)  = 0;               /* Port B: open drain configuration */
+    VALUE(TRISC) = 0xFFFF;          /* Port C: mask of inputs */
+    VALUE(PORTC) = 0xFFFF;          /* Port C: read inputs, write outputs */
+    VALUE(LATC)  = 0xFFFF;          /* Port C: read/write outputs */
+    VALUE(ODCC)  = 0;               /* Port C: open drain configuration */
+    VALUE(TRISD) = 0xFFFF;          /* Port D: mask of inputs */
+    VALUE(PORTD) = 0xFFFF;          /* Port D: read inputs, write outputs */
+    VALUE(LATD)  = 0xFFFF;          /* Port D: read/write outputs */
+    VALUE(ODCD)  = 0;               /* Port D: open drain configuration */
+    VALUE(TRISE) = 0xFFFF;          /* Port E: mask of inputs */
+    VALUE(PORTE) = 0xFFFF;          /* Port D: read inputs, write outputs */
+    VALUE(LATE)  = 0xFFFF;          /* Port E: read/write outputs */
+    VALUE(ODCE)  = 0;               /* Port E: open drain configuration */
+    VALUE(TRISF) = 0xFFFF;          /* Port F: mask of inputs */
+    VALUE(PORTF) = 0xFFFF;          /* Port F: read inputs, write outputs */
+    VALUE(LATF)  = 0xFFFF;          /* Port F: read/write outputs */
+    VALUE(ODCF)  = 0;               /* Port F: open drain configuration */
+    VALUE(TRISG) = 0xFFFF;          /* Port G: mask of inputs */
+    VALUE(PORTG) = 0xFFFF;          /* Port G: read inputs, write outputs */
+    VALUE(LATG)  = 0xFFFF;          /* Port G: read/write outputs */
+    VALUE(ODCG)  = 0;               /* Port G: open drain configuration */
+    VALUE(CNCON) = 0;               /* Interrupt-on-change control */
+    VALUE(CNEN)  = 0;               /* Input change interrupt enable */
+    VALUE(CNPUE) = 0;               /* Input pin pull-up enable */
+
+    /*
+     * Reset UARTs.
+     */
+    VALUE(U1MODE)  = 0;
+    VALUE(U1STA)   = PIC32_USTA_RIDLE | PIC32_USTA_TRMT;
+    VALUE(U1TXREG) = 0;
+    VALUE(U1RXREG) = 0;
+    VALUE(U1BRG)   = 0;
+    VALUE(U2MODE)  = 0;
+    VALUE(U2STA)   = PIC32_USTA_RIDLE | PIC32_USTA_TRMT;
+    VALUE(U2TXREG) = 0;
+    VALUE(U2RXREG) = 0;
+    VALUE(U2BRG)   = 0;
+    VALUE(U3MODE)  = 0;
+    VALUE(U3STA)   = PIC32_USTA_RIDLE | PIC32_USTA_TRMT;
+    VALUE(U3TXREG) = 0;
+    VALUE(U3RXREG) = 0;
+    VALUE(U3BRG)   = 0;
+    VALUE(U4MODE)  = 0;
+    VALUE(U4STA)   = PIC32_USTA_RIDLE | PIC32_USTA_TRMT;
+    VALUE(U4TXREG) = 0;
+    VALUE(U4RXREG) = 0;
+    VALUE(U4BRG)   = 0;
+    VALUE(U5MODE)  = 0;
+    VALUE(U5STA)   = PIC32_USTA_RIDLE | PIC32_USTA_TRMT;
+    VALUE(U5TXREG) = 0;
+    VALUE(U5RXREG) = 0;
+    VALUE(U5BRG)   = 0;
+    VALUE(U6MODE)  = 0;
+    VALUE(U6STA)   = PIC32_USTA_RIDLE | PIC32_USTA_TRMT;
+    VALUE(U6TXREG) = 0;
+    VALUE(U6RXREG) = 0;
+    VALUE(U6BRG)   = 0;
+
+    /*
+     * Reset SPI.
+     */
+    VALUE(SPI1CON)  = 0;
+    VALUE(SPI1STAT) = PIC32_SPISTAT_SPITBE;     /* Transmit buffer is empty */
+    VALUE(SPI1BRG)  = 0;
+
+    VALUE(SPI2CON)  = 0;
+    VALUE(SPI2STAT) = PIC32_SPISTAT_SPITBE;     /* Transmit buffer is empty */
+    VALUE(SPI2BRG)  = 0;
+
+    VALUE(SPI3CON)  = 0;
+    VALUE(SPI3STAT) = PIC32_SPISTAT_SPITBE;     /* Transmit buffer is empty */
+    VALUE(SPI3BRG)  = 0;
+
+    VALUE(SPI4CON)  = 0;
+    VALUE(SPI4STAT) = PIC32_SPISTAT_SPITBE;     /* Transmit buffer is empty */
+    VALUE(SPI4BRG)  = 0;
+
+    for (i = 0; i < NUM_SPI; i++) {
+        s->spi[i].rfifo = 0;
+        s->spi[i].wfifo = 0;
+    }
+}
+
+static unsigned io_read32(pic32_t *s, unsigned offset, const char **namep)
+{
+    unsigned *bufp = &VALUE(offset);
+
+    switch (offset) {
+    /*-------------------------------------------------------------------------
+     * Bus matrix control registers.
+     */
+    STORAGE(BMXCON); break;     /* Bus Mmatrix Control */
+    STORAGE(BMXDKPBA); break;   /* Data RAM kernel program base address */
+    STORAGE(BMXDUDBA); break;   /* Data RAM user data base address */
+    STORAGE(BMXDUPBA); break;   /* Data RAM user program base address */
+    STORAGE(BMXPUPBA); break;   /* Program Flash user program base address */
+    STORAGE(BMXDRMSZ); break;   /* Data RAM memory size */
+    STORAGE(BMXPFMSZ); break;   /* Program Flash memory size */
+    STORAGE(BMXBOOTSZ); break;  /* Boot Flash size */
+
+    /*-------------------------------------------------------------------------
+     * Interrupt controller registers.
+     */
+    STORAGE(INTCON); break;     /* Interrupt Control */
+    STORAGE(INTSTAT); break;    /* Interrupt Status */
+    STORAGE(IFS0); break;       /* IFS(0..2) - Interrupt Flag Status */
+    STORAGE(IFS1); break;
+    STORAGE(IFS2); break;
+    STORAGE(IEC0); break;       /* IEC(0..2) - Interrupt Enable Control */
+    STORAGE(IEC1); break;
+    STORAGE(IEC2); break;
+    STORAGE(IPC0); break;       /* IPC(0..11) - Interrupt Priority Control */
+    STORAGE(IPC1); break;
+    STORAGE(IPC2); break;
+    STORAGE(IPC3); break;
+    STORAGE(IPC4); break;
+    STORAGE(IPC5); break;
+    STORAGE(IPC6); break;
+    STORAGE(IPC7); break;
+    STORAGE(IPC8); break;
+    STORAGE(IPC9); break;
+    STORAGE(IPC10); break;
+    STORAGE(IPC11); break;
+    STORAGE(IPC12); break;
+
+    /*-------------------------------------------------------------------------
+     * Prefetch controller.
+     */
+    STORAGE(CHECON); break;     /* Prefetch Control */
+
+    /*-------------------------------------------------------------------------
+     * System controller.
+     */
+    STORAGE(OSCCON); break;     /* Oscillator Control */
+    STORAGE(OSCTUN); break;     /* Oscillator Tuning */
+    STORAGE(DDPCON); break;     /* Debug Data Port Control */
+    STORAGE(DEVID); break;      /* Device Identifier */
+    STORAGE(SYSKEY); break;     /* System Key */
+    STORAGE(RCON); break;       /* Reset Control */
+    STORAGE(RSWRST);            /* Software Reset */
+        if ((VALUE(RSWRST) & 1) && s->stop_on_reset) {
+            exit(0);
+        }
+        break;
+
+    /*-------------------------------------------------------------------------
+     * DMA controller.
+     */
+    STORAGE(DMACON); break;     /* DMA Control */
+    STORAGE(DMASTAT); break;    /* DMA Status */
+    STORAGE(DMAADDR); break;    /* DMA Address */
+
+    /*-------------------------------------------------------------------------
+     * Analog to digital converter.
+     */
+    STORAGE(AD1CON1); break;    /* Control register 1 */
+    STORAGE(AD1CON2); break;    /* Control register 2 */
+    STORAGE(AD1CON3); break;    /* Control register 3 */
+    STORAGE(AD1CHS); break;     /* Channel select */
+    STORAGE(AD1CSSL); break;    /* Input scan selection */
+    STORAGE(AD1PCFG); break;    /* Port configuration */
+    STORAGE(ADC1BUF0); break;   /* Result words */
+    STORAGE(ADC1BUF1); break;
+    STORAGE(ADC1BUF2); break;
+    STORAGE(ADC1BUF3); break;
+    STORAGE(ADC1BUF4); break;
+    STORAGE(ADC1BUF5); break;
+    STORAGE(ADC1BUF6); break;
+    STORAGE(ADC1BUF7); break;
+    STORAGE(ADC1BUF8); break;
+    STORAGE(ADC1BUF9); break;
+    STORAGE(ADC1BUFA); break;
+    STORAGE(ADC1BUFB); break;
+    STORAGE(ADC1BUFC); break;
+    STORAGE(ADC1BUFD); break;
+    STORAGE(ADC1BUFE); break;
+    STORAGE(ADC1BUFF); break;
+
+    /*--------------------------------------
+     * USB registers.
+     */
+    STORAGE(U1OTGIR); break;    /* OTG interrupt flags */
+    STORAGE(U1OTGIE); break;    /* OTG interrupt enable */
+    STORAGE(U1OTGSTAT); break;  /* Comparator and pin status */
+    STORAGE(U1OTGCON); break;   /* Resistor and pin control */
+    STORAGE(U1PWRC); break;     /* Power control */
+    STORAGE(U1IR); break;       /* Pending interrupt */
+    STORAGE(U1IE); break;       /* Interrupt enable */
+    STORAGE(U1EIR); break;      /* Pending error interrupt */
+    STORAGE(U1EIE); break;      /* Error interrupt enable */
+    STORAGE(U1STAT); break;     /* Status FIFO */
+    STORAGE(U1CON); break;      /* Control */
+    STORAGE(U1ADDR); break;     /* Address */
+    STORAGE(U1BDTP1); break;    /* Buffer descriptor table pointer 1 */
+    STORAGE(U1FRML); break;     /* Frame counter low */
+    STORAGE(U1FRMH); break;     /* Frame counter high */
+    STORAGE(U1TOK); break;      /* Host control */
+    STORAGE(U1SOF); break;      /* SOF counter */
+    STORAGE(U1BDTP2); break;    /* Buffer descriptor table pointer 2 */
+    STORAGE(U1BDTP3); break;    /* Buffer descriptor table pointer 3 */
+    STORAGE(U1CNFG1); break;    /* Debug and idle */
+    STORAGE(U1EP(0)); break;    /* Endpoint control */
+    STORAGE(U1EP(1)); break;
+    STORAGE(U1EP(2)); break;
+    STORAGE(U1EP(3)); break;
+    STORAGE(U1EP(4)); break;
+    STORAGE(U1EP(5)); break;
+    STORAGE(U1EP(6)); break;
+    STORAGE(U1EP(7)); break;
+    STORAGE(U1EP(8)); break;
+    STORAGE(U1EP(9)); break;
+    STORAGE(U1EP(10)); break;
+    STORAGE(U1EP(11)); break;
+    STORAGE(U1EP(12)); break;
+    STORAGE(U1EP(13)); break;
+    STORAGE(U1EP(14)); break;
+    STORAGE(U1EP(15)); break;
+
+    /*-------------------------------------------------------------------------
+     * General purpose IO signals.
+     */
+    STORAGE(TRISA); break;      /* Port A: mask of inputs */
+    STORAGE(PORTA); break;      /* Port A: read inputs */
+    STORAGE(LATA); break;       /* Port A: read outputs */
+    STORAGE(ODCA); break;       /* Port A: open drain configuration */
+    STORAGE(TRISB); break;      /* Port B: mask of inputs */
+    STORAGE(PORTB); break;      /* Port B: read inputs */
+    STORAGE(LATB); break;       /* Port B: read outputs */
+    STORAGE(ODCB); break;       /* Port B: open drain configuration */
+    STORAGE(TRISC); break;      /* Port C: mask of inputs */
+    STORAGE(PORTC); break;      /* Port C: read inputs */
+    STORAGE(LATC); break;       /* Port C: read outputs */
+    STORAGE(ODCC); break;       /* Port C: open drain configuration */
+    STORAGE(TRISD); break;      /* Port D: mask of inputs */
+    STORAGE(PORTD); break;      /* Port D: read inputs */
+    STORAGE(LATD); break;       /* Port D: read outputs */
+    STORAGE(ODCD); break;       /* Port D: open drain configuration */
+    STORAGE(TRISE); break;      /* Port E: mask of inputs */
+    STORAGE(PORTE); break;      /* Port E: read inputs */
+    STORAGE(LATE); break;       /* Port E: read outputs */
+    STORAGE(ODCE); break;       /* Port E: open drain configuration */
+    STORAGE(TRISF); break;      /* Port F: mask of inputs */
+    STORAGE(PORTF); break;      /* Port F: read inputs */
+    STORAGE(LATF); break;       /* Port F: read outputs */
+    STORAGE(ODCF); break;       /* Port F: open drain configuration */
+    STORAGE(TRISG); break;      /* Port G: mask of inputs */
+    STORAGE(PORTG); break;      /* Port G: read inputs */
+    STORAGE(LATG); break;       /* Port G: read outputs */
+    STORAGE(ODCG); break;       /* Port G: open drain configuration */
+    STORAGE(CNCON); break;      /* Interrupt-on-change control */
+    STORAGE(CNEN); break;       /* Input change interrupt enable */
+    STORAGE(CNPUE); break;      /* Input pin pull-up enable */
+
+    /*-------------------------------------------------------------------------
+     * UART 1.
+     */
+    STORAGE(U1RXREG);                           /* Receive data */
+        *bufp = pic32_uart_get_char(s, 0);
+        break;
+    STORAGE(U1BRG); break;                      /* Baud rate */
+    STORAGE(U1MODE); break;                     /* Mode */
+    STORAGE(U1STA);                             /* Status and control */
+        pic32_uart_poll_status(s, 0);
+        break;
+    STORAGE(U1TXREG);   *bufp = 0; break;       /* Transmit */
+    STORAGE(U1MODECLR); *bufp = 0; break;
+    STORAGE(U1MODESET); *bufp = 0; break;
+    STORAGE(U1MODEINV); *bufp = 0; break;
+    STORAGE(U1STACLR);  *bufp = 0; break;
+    STORAGE(U1STASET);  *bufp = 0; break;
+    STORAGE(U1STAINV);  *bufp = 0; break;
+    STORAGE(U1BRGCLR);  *bufp = 0; break;
+    STORAGE(U1BRGSET);  *bufp = 0; break;
+    STORAGE(U1BRGINV);  *bufp = 0; break;
+
+    /*-------------------------------------------------------------------------
+     * UART 2.
+     */
+    STORAGE(U2RXREG);                           /* Receive data */
+        *bufp = pic32_uart_get_char(s, 1);
+        break;
+    STORAGE(U2BRG); break;                      /* Baud rate */
+    STORAGE(U2MODE); break;                     /* Mode */
+    STORAGE(U2STA);                             /* Status and control */
+        pic32_uart_poll_status(s, 1);
+        break;
+    STORAGE(U2TXREG);   *bufp = 0; break;      /* Transmit */
+    STORAGE(U2MODECLR); *bufp = 0; break;
+    STORAGE(U2MODESET); *bufp = 0; break;
+    STORAGE(U2MODEINV); *bufp = 0; break;
+    STORAGE(U2STACLR);  *bufp = 0; break;
+    STORAGE(U2STASET);  *bufp = 0; break;
+    STORAGE(U2STAINV);  *bufp = 0; break;
+    STORAGE(U2BRGCLR);  *bufp = 0; break;
+    STORAGE(U2BRGSET);  *bufp = 0; break;
+    STORAGE(U2BRGINV);  *bufp = 0; break;
+
+    /*-------------------------------------------------------------------------
+     * UART 3.
+     */
+    STORAGE(U3RXREG);                           /* Receive data */
+        *bufp = pic32_uart_get_char(s, 2);
+        break;
+    STORAGE(U3BRG); break;                      /* Baud rate */
+    STORAGE(U3MODE); break;                     /* Mode */
+    STORAGE(U3STA);                             /* Status and control */
+        pic32_uart_poll_status(s, 2);
+        break;
+    STORAGE(U3TXREG);   *bufp = 0; break;       /* Transmit */
+    STORAGE(U3MODECLR); *bufp = 0; break;
+    STORAGE(U3MODESET); *bufp = 0; break;
+    STORAGE(U3MODEINV); *bufp = 0; break;
+    STORAGE(U3STACLR);  *bufp = 0; break;
+    STORAGE(U3STASET);  *bufp = 0; break;
+    STORAGE(U3STAINV);  *bufp = 0; break;
+    STORAGE(U3BRGCLR);  *bufp = 0; break;
+    STORAGE(U3BRGSET);  *bufp = 0; break;
+    STORAGE(U3BRGINV);  *bufp = 0; break;
+
+    /*-------------------------------------------------------------------------
+     * UART 4.
+     */
+    STORAGE(U4RXREG);                           /* Receive data */
+        *bufp = pic32_uart_get_char(s, 3);
+        break;
+    STORAGE(U4BRG); break;                      /* Baud rate */
+    STORAGE(U4MODE); break;                     /* Mode */
+    STORAGE(U4STA);                             /* Status and control */
+        pic32_uart_poll_status(s, 3);
+        break;
+    STORAGE(U4TXREG);   *bufp = 0; break;       /* Transmit */
+    STORAGE(U4MODECLR); *bufp = 0; break;
+    STORAGE(U4MODESET); *bufp = 0; break;
+    STORAGE(U4MODEINV); *bufp = 0; break;
+    STORAGE(U4STACLR);  *bufp = 0; break;
+    STORAGE(U4STASET);  *bufp = 0; break;
+    STORAGE(U4STAINV);  *bufp = 0; break;
+    STORAGE(U4BRGCLR);  *bufp = 0; break;
+    STORAGE(U4BRGSET);  *bufp = 0; break;
+    STORAGE(U4BRGINV);  *bufp = 0; break;
+
+    /*-------------------------------------------------------------------------
+     * UART 5.
+     */
+    STORAGE(U5RXREG);                           /* Receive data */
+        *bufp = pic32_uart_get_char(s, 4);
+        break;
+    STORAGE(U5BRG); break;                      /* Baud rate */
+    STORAGE(U5MODE); break;                     /* Mode */
+    STORAGE(U5STA);                             /* Status and control */
+        pic32_uart_poll_status(s, 4);
+        break;
+    STORAGE(U5TXREG);   *bufp = 0; break;       /* Transmit */
+    STORAGE(U5MODECLR); *bufp = 0; break;
+    STORAGE(U5MODESET); *bufp = 0; break;
+    STORAGE(U5MODEINV); *bufp = 0; break;
+    STORAGE(U5STACLR);  *bufp = 0; break;
+    STORAGE(U5STASET);  *bufp = 0; break;
+    STORAGE(U5STAINV);  *bufp = 0; break;
+    STORAGE(U5BRGCLR);  *bufp = 0; break;
+    STORAGE(U5BRGSET);  *bufp = 0; break;
+    STORAGE(U5BRGINV);  *bufp = 0; break;
+
+    /*-------------------------------------------------------------------------
+     * UART 6.
+     */
+    STORAGE(U6RXREG);                           /* Receive data */
+        *bufp = pic32_uart_get_char(s, 5);
+        break;
+    STORAGE(U6BRG); break;                      /* Baud rate */
+    STORAGE(U6MODE); break;                     /* Mode */
+    STORAGE(U6STA);                             /* Status and control */
+        pic32_uart_poll_status(s, 5);
+        break;
+    STORAGE(U6TXREG);   *bufp = 0; break;       /* Transmit */
+    STORAGE(U6MODECLR); *bufp = 0; break;
+    STORAGE(U6MODESET); *bufp = 0; break;
+    STORAGE(U6MODEINV); *bufp = 0; break;
+    STORAGE(U6STACLR);  *bufp = 0; break;
+    STORAGE(U6STASET);  *bufp = 0; break;
+    STORAGE(U6STAINV);  *bufp = 0; break;
+    STORAGE(U6BRGCLR);  *bufp = 0; break;
+    STORAGE(U6BRGSET);  *bufp = 0; break;
+    STORAGE(U6BRGINV);  *bufp = 0; break;
+
+    /*-------------------------------------------------------------------------
+     * SPI 1.
+     */
+    STORAGE(SPI1CON); break;                    /* Control */
+    STORAGE(SPI1CONCLR); *bufp = 0; break;
+    STORAGE(SPI1CONSET); *bufp = 0; break;
+    STORAGE(SPI1CONINV); *bufp = 0; break;
+    STORAGE(SPI1STAT); break;                   /* Status */
+    STORAGE(SPI1STATCLR); *bufp = 0; break;
+    STORAGE(SPI1STATSET); *bufp = 0; break;
+    STORAGE(SPI1STATINV); *bufp = 0; break;
+    STORAGE(SPI1BUF);                           /* Buffer */
+        *bufp = pic32_spi_readbuf(s, 0);
+        break;
+    STORAGE(SPI1BRG); break;                    /* Baud rate */
+    STORAGE(SPI1BRGCLR); *bufp = 0; break;
+    STORAGE(SPI1BRGSET); *bufp = 0; break;
+    STORAGE(SPI1BRGINV); *bufp = 0; break;
+
+    /*-------------------------------------------------------------------------
+     * SPI 2.
+     */
+    STORAGE(SPI2CON); break;                    /* Control */
+    STORAGE(SPI2CONCLR); *bufp = 0; break;
+    STORAGE(SPI2CONSET); *bufp = 0; break;
+    STORAGE(SPI2CONINV); *bufp = 0; break;
+    STORAGE(SPI2STAT); break;                   /* Status */
+    STORAGE(SPI2STATCLR); *bufp = 0; break;
+    STORAGE(SPI2STATSET); *bufp = 0; break;
+    STORAGE(SPI2STATINV); *bufp = 0; break;
+    STORAGE(SPI2BUF);                           /* Buffer */
+        *bufp = pic32_spi_readbuf(s, 1);
+        break;
+    STORAGE(SPI2BRG); break;                    /* Baud rate */
+    STORAGE(SPI2BRGCLR); *bufp = 0; break;
+    STORAGE(SPI2BRGSET); *bufp = 0; break;
+    STORAGE(SPI2BRGINV); *bufp = 0; break;
+
+    /*-------------------------------------------------------------------------
+     * SPI 3.
+     */
+    STORAGE(SPI3CON); break;                    /* Control */
+    STORAGE(SPI3CONCLR); *bufp = 0; break;
+    STORAGE(SPI3CONSET); *bufp = 0; break;
+    STORAGE(SPI3CONINV); *bufp = 0; break;
+    STORAGE(SPI3STAT); break;                   /* Status */
+    STORAGE(SPI3STATCLR); *bufp = 0; break;
+    STORAGE(SPI3STATSET); *bufp = 0; break;
+    STORAGE(SPI3STATINV); *bufp = 0; break;
+    STORAGE(SPI3BUF);                           /* SPIx Buffer */
+        *bufp = pic32_spi_readbuf(s, 2);
+        break;
+    STORAGE(SPI3BRG); break;                    /* Baud rate */
+    STORAGE(SPI3BRGCLR); *bufp = 0; break;
+    STORAGE(SPI3BRGSET); *bufp = 0; break;
+    STORAGE(SPI3BRGINV); *bufp = 0; break;
+
+    /*-------------------------------------------------------------------------
+     * SPI 4.
+     */
+    STORAGE(SPI4CON); break;                    /* Control */
+    STORAGE(SPI4CONCLR); *bufp = 0; break;
+    STORAGE(SPI4CONSET); *bufp = 0; break;
+    STORAGE(SPI4CONINV); *bufp = 0; break;
+    STORAGE(SPI4STAT); break;                   /* Status */
+    STORAGE(SPI4STATCLR); *bufp = 0; break;
+    STORAGE(SPI4STATSET); *bufp = 0; break;
+    STORAGE(SPI4STATINV); *bufp = 0; break;
+    STORAGE(SPI4BUF);                           /* Buffer */
+        *bufp = pic32_spi_readbuf(s, 3);
+        break;
+    STORAGE(SPI4BRG); break;                    /* Baud rate */
+    STORAGE(SPI4BRGCLR); *bufp = 0; break;
+    STORAGE(SPI4BRGSET); *bufp = 0; break;
+    STORAGE(SPI4BRGINV); *bufp = 0; break;
+
+    default:
+        printf("--- Read 1f8%05x: peripheral register not supported\n",
+            offset);
+        if (TRACE) {
+            fprintf(qemu_logfile,
+                "--- Read 1f8%05x: peripheral register not supported\n",
+                offset);
+        }
+        exit(1);
+    }
+    return *bufp;
+}
+
+static void io_write32(pic32_t *s, unsigned offset, unsigned data,
+    const char **namep)
+{
+    unsigned *bufp = &VALUE(offset);
+
+    switch (offset) {
+    /*-------------------------------------------------------------------------
+     * Bus matrix control registers.
+     */
+    WRITEOP(BMXCON); return;    /* Bus Matrix Control */
+    STORAGE(BMXDKPBA); break;   /* Data RAM kernel program base address */
+    STORAGE(BMXDUDBA); break;   /* Data RAM user data base address */
+    STORAGE(BMXDUPBA); break;   /* Data RAM user program base address */
+    STORAGE(BMXPUPBA); break;   /* Program Flash user program base address */
+    READONLY(BMXDRMSZ);         /* Data RAM memory size */
+    READONLY(BMXPFMSZ);         /* Program Flash memory size */
+    READONLY(BMXBOOTSZ);        /* Boot Flash size */
+
+    /*-------------------------------------------------------------------------
+     * Interrupt controller registers.
+     */
+    WRITEOP(INTCON); return;    /* Interrupt Control */
+    READONLY(INTSTAT);          /* Interrupt Status */
+    WRITEOP(IPTMR);  return;    /* Temporal Proximity Timer */
+    WRITEOP(IFS0); goto irq;    /* IFS(0..2) - Interrupt Flag Status */
+    WRITEOP(IFS1); goto irq;
+    WRITEOP(IFS2); goto irq;
+    WRITEOP(IEC0); goto irq;    /* IEC(0..2) - Interrupt Enable Control */
+    WRITEOP(IEC1); goto irq;
+    WRITEOP(IEC2); goto irq;
+    WRITEOP(IPC0); goto irq;    /* IPC(0..11) - Interrupt Priority Control */
+    WRITEOP(IPC1); goto irq;
+    WRITEOP(IPC2); goto irq;
+    WRITEOP(IPC3); goto irq;
+    WRITEOP(IPC4); goto irq;
+    WRITEOP(IPC5); goto irq;
+    WRITEOP(IPC6); goto irq;
+    WRITEOP(IPC7); goto irq;
+    WRITEOP(IPC8); goto irq;
+    WRITEOP(IPC9); goto irq;
+    WRITEOP(IPC10); goto irq;
+    WRITEOP(IPC11); goto irq;
+    WRITEOP(IPC12);
+irq:    update_irq_status(s);
+        return;
+
+    /*-------------------------------------------------------------------------
+     * Prefetch controller.
+     */
+    WRITEOP(CHECON);                        /* Prefetch Control */
+        return;
+
+    /*-------------------------------------------------------------------------
+     * System controller.
+     */
+    WRITEOPR(OSCCON, PIC32_OSCCON_UNUSED);  /* Oscillator Control */
+        break;
+    WRITEOPR(OSCTUN, PIC32_OSCTUN_UNUSED);  /* Oscillator Tuning */
+        break;
+    STORAGE(DDPCON);                        /* Debug Data Port Control */
+        break;
+    READONLY(DEVID);                        /* Device Identifier */
+
+    STORAGE(SYSKEY);                        /* System Key */
+        /* Unlock state machine. */
+        if (s->syskey_unlock == 0 && VALUE(SYSKEY) == 0xaa996655) {
+            s->syskey_unlock = 1;
+        }
+        if (s->syskey_unlock == 1 && VALUE(SYSKEY) == 0x556699aa) {
+            s->syskey_unlock = 2;
+        } else {
+            s->syskey_unlock = 0;
+        }
+        break;
+    WRITEOPR(RCON, PIC32_RCON_UNUSED);      /* Reset Control */
+        break;
+    WRITEOP(RSWRST);                        /* Software Reset */
+        if (s->syskey_unlock == 2 && (VALUE(RSWRST) & 1)) {
+            /* Reset CPU. */
+            qemu_system_reset_request();
+
+            /* Reset all devices */
+            io_reset(s);
+            pic32_sdcard_reset(s);
+        }
+        break;
+
+    /*-------------------------------------------------------------------------
+     * DMA controller.
+     */
+    WRITEOP(DMACON); return;    /* DMA Control */
+    STORAGE(DMASTAT); break;    /* DMA Status */
+    STORAGE(DMAADDR); break;    /* DMA Address */
+
+    /*-------------------------------------------------------------------------
+     * Analog to digital converter.
+     */
+    WRITEOP(AD1CON1); return;   /* Control register 1 */
+    WRITEOP(AD1CON2); return;   /* Control register 2 */
+    WRITEOP(AD1CON3); return;   /* Control register 3 */
+    WRITEOP(AD1CHS); return;    /* Channel select */
+    WRITEOP(AD1CSSL); return;   /* Input scan selection */
+    WRITEOP(AD1PCFG); return;   /* Port configuration */
+    READONLY(ADC1BUF0);         /* Result words */
+    READONLY(ADC1BUF1);
+    READONLY(ADC1BUF2);
+    READONLY(ADC1BUF3);
+    READONLY(ADC1BUF4);
+    READONLY(ADC1BUF5);
+    READONLY(ADC1BUF6);
+    READONLY(ADC1BUF7);
+    READONLY(ADC1BUF8);
+    READONLY(ADC1BUF9);
+    READONLY(ADC1BUFA);
+    READONLY(ADC1BUFB);
+    READONLY(ADC1BUFC);
+    READONLY(ADC1BUFD);
+    READONLY(ADC1BUFE);
+    READONLY(ADC1BUFF);
+
+    /*--------------------------------------
+     * USB registers.
+     */
+    STORAGE(U1OTGIR);           /* OTG interrupt flags */
+        VALUE(U1OTGIR) = 0;
+        return;
+    STORAGE(U1OTGIE); break;    /* OTG interrupt enable */
+    READONLY(U1OTGSTAT);        /* Comparator and pin status */
+    STORAGE(U1OTGCON); break;   /* Resistor and pin control */
+    STORAGE(U1PWRC); break;     /* Power control */
+    STORAGE(U1IR);              /* Pending interrupt */
+        VALUE(U1IR) = 0;
+        return;
+    STORAGE(U1IE); break;       /* Interrupt enable */
+    STORAGE(U1EIR);             /* Pending error interrupt */
+        VALUE(U1EIR) = 0;
+        return;
+    STORAGE(U1EIE); break;      /* Error interrupt enable */
+    READONLY(U1STAT);           /* Status FIFO */
+    STORAGE(U1CON); break;      /* Control */
+    STORAGE(U1ADDR); break;     /* Address */
+    STORAGE(U1BDTP1); break;    /* Buffer descriptor table pointer 1 */
+    READONLY(U1FRML);           /* Frame counter low */
+    READONLY(U1FRMH);           /* Frame counter high */
+    STORAGE(U1TOK); break;      /* Host control */
+    STORAGE(U1SOF); break;      /* SOF counter */
+    STORAGE(U1BDTP2); break;    /* Buffer descriptor table pointer 2 */
+    STORAGE(U1BDTP3); break;    /* Buffer descriptor table pointer 3 */
+    STORAGE(U1CNFG1); break;    /* Debug and idle */
+    STORAGE(U1EP(0)); break;    /* Endpoint control */
+    STORAGE(U1EP(1)); break;
+    STORAGE(U1EP(2)); break;
+    STORAGE(U1EP(3)); break;
+    STORAGE(U1EP(4)); break;
+    STORAGE(U1EP(5)); break;
+    STORAGE(U1EP(6)); break;
+    STORAGE(U1EP(7)); break;
+    STORAGE(U1EP(8)); break;
+    STORAGE(U1EP(9)); break;
+    STORAGE(U1EP(10)); break;
+    STORAGE(U1EP(11)); break;
+    STORAGE(U1EP(12)); break;
+    STORAGE(U1EP(13)); break;
+    STORAGE(U1EP(14)); break;
+    STORAGE(U1EP(15)); break;
+
+    /*-------------------------------------------------------------------------
+     * General purpose IO signals.
+     */
+    WRITEOP(TRISA); return;         /* Port A: mask of inputs */
+    WRITEOPX(PORTA, LATA);          /* Port A: write outputs */
+    WRITEOP(LATA);                  /* Port A: write outputs */
+        pic32_gpio_write(s, 0, VALUE(LATA));
+        return;
+    WRITEOP(ODCA); return;          /* Port A: open drain configuration */
+    WRITEOP(TRISB); return;         /* Port B: mask of inputs */
+    WRITEOPX(PORTB, LATB);          /* Port B: write outputs */
+    WRITEOP(LATB);                  /* Port B: write outputs */
+        pic32_gpio_write(s, 1, VALUE(LATB));
+        return;
+    WRITEOP(ODCB); return;          /* Port B: open drain configuration */
+    WRITEOP(TRISC); return;         /* Port C: mask of inputs */
+    WRITEOPX(PORTC, LATC);          /* Port C: write outputs */
+    WRITEOP(LATC);                  /* Port C: write outputs */
+        pic32_gpio_write(s, 2, VALUE(LATC));
+        return;
+    WRITEOP(ODCC); return;          /* Port C: open drain configuration */
+    WRITEOP(TRISD); return;         /* Port D: mask of inputs */
+    WRITEOPX(PORTD, LATD);          /* Port D: write outputs */
+    WRITEOP(LATD);                  /* Port D: write outputs */
+        pic32_gpio_write(s, 3, VALUE(LATD));
+        return;
+    WRITEOP(ODCD); return;          /* Port D: open drain configuration */
+    WRITEOP(TRISE); return;         /* Port E: mask of inputs */
+    WRITEOPX(PORTE, LATE);          /* Port E: write outputs */
+    WRITEOP(LATE);                  /* Port E: write outputs */
+        pic32_gpio_write(s, 4, VALUE(LATE));
+        return;
+    WRITEOP(ODCE); return;          /* Port E: open drain configuration */
+    WRITEOP(TRISF); return;         /* Port F: mask of inputs */
+    WRITEOPX(PORTF, LATF);          /* Port F: write outputs */
+    WRITEOP(LATF);                  /* Port F: write outputs */
+        pic32_gpio_write(s, 5, VALUE(LATF));
+        return;
+    WRITEOP(ODCF); return;          /* Port F: open drain configuration */
+    WRITEOP(TRISG); return;         /* Port G: mask of inputs */
+    WRITEOPX(PORTG, LATG);          /* Port G: write outputs */
+    WRITEOP(LATG);                  /* Port G: write outputs */
+        pic32_gpio_write(s, 6, VALUE(LATG));
+        return;
+    WRITEOP(ODCG); return;          /* Port G: open drain configuration */
+    WRITEOP(CNCON); return;         /* Interrupt-on-change control */
+    WRITEOP(CNEN); return;          /* Input change interrupt enable */
+    WRITEOP(CNPUE); return;         /* Input pin pull-up enable */
+
+    /*-------------------------------------------------------------------------
+     * UART 1.
+     */
+    STORAGE(U1TXREG);                               /* Transmit */
+        pic32_uart_put_char(s, 0, data);
+        break;
+    WRITEOP(U1MODE);                                /* Mode */
+        pic32_uart_update_mode(s, 0);
+        return;
+    WRITEOPR(U1STA,                                 /* Status and control */
+        PIC32_USTA_URXDA | PIC32_USTA_FERR | PIC32_USTA_PERR |
+        PIC32_USTA_RIDLE | PIC32_USTA_TRMT | PIC32_USTA_UTXBF);
+        pic32_uart_update_status(s, 0);
+        return;
+    WRITEOP(U1BRG); return;                         /* Baud rate */
+    READONLY(U1RXREG);                              /* Receive */
+
+    /*-------------------------------------------------------------------------
+     * UART 2.
+     */
+    STORAGE(U2TXREG);                               /* Transmit */
+        pic32_uart_put_char(s, 1, data);
+        break;
+    WRITEOP(U2MODE);                                /* Mode */
+        pic32_uart_update_mode(s, 1);
+        return;
+    WRITEOPR(U2STA,                                 /* Status and control */
+        PIC32_USTA_URXDA | PIC32_USTA_FERR | PIC32_USTA_PERR |
+        PIC32_USTA_RIDLE | PIC32_USTA_TRMT | PIC32_USTA_UTXBF);
+        pic32_uart_update_status(s, 1);
+        return;
+    WRITEOP(U2BRG); return;                         /* Baud rate */
+    READONLY(U2RXREG);                              /* Receive */
+
+    /*-------------------------------------------------------------------------
+     * UART 3.
+     */
+    STORAGE(U3TXREG);                               /* Transmit */
+        pic32_uart_put_char(s, 2, data);
+        break;
+    WRITEOP(U3MODE);                                /* Mode */
+        pic32_uart_update_mode(s, 2);
+        return;
+    WRITEOPR(U3STA,                                 /* Status and control */
+        PIC32_USTA_URXDA | PIC32_USTA_FERR | PIC32_USTA_PERR |
+        PIC32_USTA_RIDLE | PIC32_USTA_TRMT | PIC32_USTA_UTXBF);
+        pic32_uart_update_status(s, 2);
+        return;
+    WRITEOP(U3BRG); return;                         /* Baud rate */
+    READONLY(U3RXREG);                              /* Receive */
+
+    /*-------------------------------------------------------------------------
+     * UART 4.
+     */
+    STORAGE(U4TXREG);                               /* Transmit */
+        pic32_uart_put_char(s, 3, data);
+        break;
+    WRITEOP(U4MODE);                                /* Mode */
+        pic32_uart_update_mode(s, 3);
+        return;
+    WRITEOPR(U4STA,                                 /* Status and control */
+        PIC32_USTA_URXDA | PIC32_USTA_FERR | PIC32_USTA_PERR |
+        PIC32_USTA_RIDLE | PIC32_USTA_TRMT | PIC32_USTA_UTXBF);
+        pic32_uart_update_status(s, 3);
+        return;
+    WRITEOP(U4BRG); return;                         /* Baud rate */
+    READONLY(U4RXREG);                              /* Receive */
+
+    /*-------------------------------------------------------------------------
+     * UART 5.
+     */
+    STORAGE(U5TXREG);                               /* Transmit */
+        pic32_uart_put_char(s, 4, data);
+        break;
+    WRITEOP(U5MODE);                                /* Mode */
+        pic32_uart_update_mode(s, 4);
+        return;
+    WRITEOPR(U5STA,                                 /* Status and control */
+        PIC32_USTA_URXDA | PIC32_USTA_FERR | PIC32_USTA_PERR |
+        PIC32_USTA_RIDLE | PIC32_USTA_TRMT | PIC32_USTA_UTXBF);
+        pic32_uart_update_status(s, 4);
+        return;
+    WRITEOP(U5BRG); return;                         /* Baud rate */
+    READONLY(U5RXREG);                              /* Receive */
+
+    /*-------------------------------------------------------------------------
+     * UART 6.
+     */
+    STORAGE(U6TXREG);                               /* Transmit */
+        pic32_uart_put_char(s, 5, data);
+        break;
+    WRITEOP(U6MODE);                                /* Mode */
+        pic32_uart_update_mode(s, 5);
+        return;
+    WRITEOPR(U6STA,                                 /* Status and control */
+        PIC32_USTA_URXDA | PIC32_USTA_FERR | PIC32_USTA_PERR |
+        PIC32_USTA_RIDLE | PIC32_USTA_TRMT | PIC32_USTA_UTXBF);
+        pic32_uart_update_status(s, 5);
+        return;
+    WRITEOP(U6BRG); return;                         /* Baud rate */
+    READONLY(U6RXREG);                              /* Receive */
+
+    /*-------------------------------------------------------------------------
+     * SPI.
+     */
+    WRITEOP(SPI1CON);                               /* Control */
+        pic32_spi_control(s, 0);
+        return;
+    WRITEOPR(SPI1STAT, ~PIC32_SPISTAT_SPIROV);      /* Status */
+        return;                                     /* Only ROV bit writable */
+    STORAGE(SPI1BUF);                               /* Buffer */
+        pic32_spi_writebuf(s, 0, data);
+        return;
+    WRITEOP(SPI1BRG); return;                       /* Baud rate */
+    WRITEOP(SPI2CON);                               /* Control */
+        pic32_spi_control(s, 1);
+        return;
+    WRITEOPR(SPI2STAT, ~PIC32_SPISTAT_SPIROV);      /* Status */
+        return;                                     /* Only ROV bit writable */
+    STORAGE(SPI2BUF);                               /* Buffer */
+        pic32_spi_writebuf(s, 1, data);
+        return;
+    WRITEOP(SPI2BRG); return;                       /* Baud rate */
+    WRITEOP(SPI3CON);                               /* Control */
+        pic32_spi_control(s, 2);
+        return;
+    WRITEOPR(SPI3STAT, ~PIC32_SPISTAT_SPIROV);      /* Status */
+        return;                                     /* Only ROV bit writable */
+    STORAGE(SPI3BUF);                               /* Buffer */
+        pic32_spi_writebuf(s, 2, data);
+        return;
+    WRITEOP(SPI3BRG); return;                       /* Baud rate */
+    WRITEOP(SPI4CON);                               /* Control */
+        pic32_spi_control(s, 3);
+        return;
+    WRITEOPR(SPI4STAT, ~PIC32_SPISTAT_SPIROV);      /* Status */
+        return;                                     /* Only ROV bit writable */
+    STORAGE(SPI4BUF);                               /* Buffer */
+        pic32_spi_writebuf(s, 3, data);
+        return;
+    WRITEOP(SPI4BRG); return;                       /* Baud rate */
+
+    default:
+        printf("--- Write %08x to 1f8%05x: peripheral register not supported\n",
+            data, offset);
+        if (TRACE) {
+            fprintf(qemu_logfile,
+            "--- Write %08x to 1f8%05x: peripheral register not supported\n",
+                data, offset);
+        }
+        exit(1);
+readonly:
+        printf("--- Write %08x to %s: readonly register\n",
+            data, *namep);
+        if (TRACE) {
+            fprintf(qemu_logfile, "--- Write %08x to %s: readonly register\n",
+                data, *namep);
+        }
+        *namep = 0;
+        return;
+    }
+    *bufp = data;
+}
+
+static uint64_t pic32_io_read(void *opaque, hwaddr addr, unsigned bytes)
+{
+    pic32_t *s = opaque;
+    uint32_t offset = addr & 0xfffff;
+    const char *name = "???";
+    uint32_t data = 0;
+
+    data = io_read32(s, offset & ~3, &name);
+    switch (bytes) {
+    case 1:
+        offset &= 3;
+        if (offset != 0) {
+            /* Unaligned read. */
+            data >>= offset * 8;
+        }
+        data = (uint8_t) data;
+        if (TRACE) {
+            fprintf(qemu_logfile, "--- I/O Read  %02x from %s\n", data, name);
+        }
+        break;
+    case 2:
+        if (offset & 2) {
+            /* Unaligned read. */
+            data >>= 16;
+        }
+        data = (uint16_t) data;
+        if (TRACE) {
+            fprintf(qemu_logfile, "--- I/O Read  %04x from %s\n", data, name);
+        }
+        break;
+    default:
+        if (TRACE) {
+            fprintf(qemu_logfile, "--- I/O Read  %08x from %s\n", data, name);
+        }
+        break;
+    }
+    return data;
+}
+
+static void pic32_io_write(void *opaque, hwaddr addr, uint64_t data,
+    unsigned bytes)
+{
+    pic32_t *s = opaque;
+    uint32_t offset = addr & 0xfffff;
+    const char *name = "???";
+
+    /* Fetch data and align to word format. */
+    switch (bytes) {
+    case 1:
+        data = (uint8_t) data;
+        data <<= (offset & 3) * 8;
+        break;
+    case 2:
+        data = (uint16_t) data;
+        data <<= (offset & 2) * 8;
+        break;
+    }
+    io_write32(s, offset & ~3, data, &name);
+
+    if (TRACE && name != 0) {
+        fprintf(qemu_logfile, "--- I/O Write %08x to %s\n",
+            (uint32_t) data, name);
+    }
+}
+
+/*
+ * This function is called when the processor is stopped
+ * on WAIT instruction, waiting for external interrupt.
+ */
+static void pic32_exec_exit(CPUState *cs)
+{
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    CPUMIPSState *env = &cpu->env;
+
+    if (cs->halted && !(env->CP0_Status & (1 << CP0St_IE))) {
+        /* WAIT instruction with interrupts disabled - halt the simulation. */
+        qemu_system_shutdown_request();
+    }
+}
+
+static const MemoryRegionOps pic32_io_ops = {
+    .read       = pic32_io_read,
+    .write      = pic32_io_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void main_cpu_reset(void *opaque)
+{
+    MIPSCPU *cpu = opaque;
+    CPUMIPSState *env = &cpu->env;
+    int i;
+
+    cpu_reset(CPU(cpu));
+
+    /* Adjust the initial configuration for M4K core. */
+    env->CP0_IntCtl = 0;
+    env->CP0_Debug = (1 << CP0DB_CNT) | (3 << CP0DB_VER);
+    for (i = 0; i < 7; i++) {
+        env->CP0_WatchHi[i] = 0;
+    }
+}
+
+static void store_byte(unsigned address, unsigned char byte)
+{
+    if (address >= PROGRAM_FLASH_START &&
+        address < PROGRAM_FLASH_START + PROGRAM_FLASH_SIZE) {
+        /*printf("Store %02x to program memory %08x\n", byte, address);*/
+        prog_ptr[address & 0xfffff] = byte;
+        return;
+    }
+
+    if (address >= BOOT_FLASH_START &&
+        address < BOOT_FLASH_START + BOOT_FLASH_SIZE) {
+        /*printf("Store %02x to boot memory %08x\n", byte, address);*/
+        boot_ptr[address & 0xffff] = byte;
+        return;
+    }
+
+    printf("Bad hex file: "
+        "incorrect address %08X, must be %08X-%08X or %08X-%08X\n",
+        address, PROGRAM_FLASH_START,
+        PROGRAM_FLASH_START + PROGRAM_FLASH_SIZE - 1,
+        BOOT_FLASH_START, BOOT_FLASH_START + BOOT_FLASH_SIZE - 1);
+    exit(1);
+}
+
+/*
+ * Ignore ^C and ^\ signals and pass these characters to the target.
+ */
+static void pic32_pass_signal_chars(void)
+{
+    struct termios tty;
+
+    tcgetattr(0, &tty);
+    tty.c_lflag &= ~ISIG;
+    tcsetattr(0, TCSANOW, &tty);
+}
+
+static void pic32_init(MachineState *machine, int board_type)
+{
+    const char *cpu_model = machine->cpu_model;
+    unsigned ram_size = DATA_MEM_SIZE;
+    MemoryRegion *system_memory = get_system_memory();
+    MemoryRegion *ram_main = g_new(MemoryRegion, 1);
+    MemoryRegion *prog_mem = g_new(MemoryRegion, 1);
+    MemoryRegion *boot_mem = g_new(MemoryRegion, 1);
+    MemoryRegion *io_mem = g_new(MemoryRegion, 1);
+    MIPSCPU *cpu;
+    CPUMIPSState *env;
+
+    DeviceState *dev = qdev_create(NULL, TYPE_MIPS_PIC32);
+    pic32_t *s = OBJECT_CHECK(pic32_t, dev, TYPE_MIPS_PIC32);
+    s->board_type = board_type;
+    s->stop_on_reset = 1;               /* halt simulation on soft reset */
+    s->iomem = g_malloc0(IO_MEM_SIZE);  /* backing storage for I/O area */
+
+    qdev_init_nofail(dev);
+
+    /* Init CPU. */
+    if (!cpu_model) {
+        cpu_model = "M4K";
+    }
+    printf("Board: %s\n", board_name[board_type]);
+    if (qemu_logfile) {
+        fprintf(qemu_logfile, "Board: %s\n", board_name[board_type]);
+    }
+
+    printf("Processor: %s\n", cpu_model);
+    if (qemu_logfile) {
+        fprintf(qemu_logfile, "Processor: %s\n", cpu_model);
+    }
+
+    cpu = cpu_mips_init(cpu_model);
+    if (!cpu) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    s->cpu = cpu;
+    env = &cpu->env;
+
+    /* Register RAM */
+    printf("RAM size: %u kbytes\n", ram_size / 1024);
+    if (qemu_logfile) {
+        fprintf(qemu_logfile, "RAM size: %u kbytes\n", ram_size / 1024);
+    }
+
+    memory_region_init_ram(ram_main, NULL, "kernel.ram",
+        ram_size, &error_abort);
+    vmstate_register_ram_global(ram_main);
+    memory_region_add_subregion(system_memory, DATA_MEM_START, ram_main);
+
+    /* Alias for user space 96 kbytes.
+     * For MX family only. */
+    MemoryRegion *ram_user = g_new(MemoryRegion, 1);
+    memory_region_init_alias(ram_user, NULL, "user.ram",
+        ram_main, 0x8000, ram_size - 0x8000);
+    memory_region_add_subregion(system_memory,
+        USER_MEM_START + 0x8000, ram_user);
+
+    /* Special function registers. */
+    memory_region_init_io(io_mem, NULL, &pic32_io_ops, s,
+                          "io", IO_MEM_SIZE);
+    memory_region_add_subregion(system_memory, IO_MEM_START, io_mem);
+
+    /*
+     * Map the flash memory.
+     */
+    memory_region_init_ram(boot_mem, NULL, "boot.flash",
+        BOOT_FLASH_SIZE, &error_abort);
+    memory_region_init_ram(prog_mem, NULL, "prog.flash",
+        PROGRAM_FLASH_SIZE, &error_abort);
+
+    /* Load a Flash memory image. */
+    if (!machine->kernel_filename) {
+        error_report("No -kernel argument was specified.");
+        exit(1);
+    }
+    prog_ptr = memory_region_get_ram_ptr(prog_mem);
+    boot_ptr = memory_region_get_ram_ptr(boot_mem);
+    if (bios_name) {
+        pic32_load_hex_file(bios_name, store_byte);
+    }
+    pic32_load_hex_file(machine->kernel_filename, store_byte);
+
+    memory_region_set_readonly(boot_mem, true);
+    memory_region_set_readonly(prog_mem, true);
+    memory_region_add_subregion(system_memory, BOOT_FLASH_START, boot_mem);
+    memory_region_add_subregion(system_memory, PROGRAM_FLASH_START, prog_mem);
+
+    /* Init internal devices */
+    s->irq_raise = irq_raise;
+    s->irq_clear = irq_clear;
+    qemu_register_reset(main_cpu_reset, cpu);
+
+    /* Setup interrupt controller in EIC mode. */
+    env->CP0_Config3 |= 1 << CP0C3_VEIC;
+    cpu_mips_irq_init_cpu(env);
+    env->eic_timer_irq = pic32_timer_irq;
+    env->eic_soft_irq = pic32_soft_irq;
+    env->eic_context = s;
+
+    /* CPU runs at 80MHz.
+     * Count register increases at half this rate. */
+    cpu_mips_clock_init(env, 40*1000*1000);
+
+    /* Setup callback for CPU halt. */
+    MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(cpu);
+    CPUClass *cc = CPU_CLASS(mcc);
+    cc->cpu_exec_exit = pic32_exec_exit;
+
+    /*
+     * Initialize board-specific parameters.
+     */
+    int cs0_port, cs0_pin, cs1_port, cs1_pin;
+    switch (board_type) {
+    default:
+    case BOARD_MAX32:
+        BOOTMEM(DEVCFG0) = 0xffffff7f;      /* Max32 board */
+        BOOTMEM(DEVCFG1) = 0x5bfd6aff;      /* console on UART1 */
+        BOOTMEM(DEVCFG2) = 0xd979f8f9;
+        BOOTMEM(DEVCFG3) = 0xffff0722;
+        VALUE(DEVID)     = 0x04307053;      /* MX795F512L */
+        VALUE(OSCCON)    = 0x01453320;      /* external oscillator 8MHz */
+        s->sdcard_spi_port = 1;             /* SD card at SPI2, */
+        cs0_port = 2;  cs0_pin = 14;        /* select0 at C14, */
+        cs1_port = 3;  cs1_pin = 1;         /* select1 at D1 */
+        break;
+    case BOARD_MAXIMITE:
+        /* TODO: get real data from Maximite board */
+        BOOTMEM(DEVCFG0) = 0xffffff7f;
+        BOOTMEM(DEVCFG1) = 0x5bfd6aff;      /* console on UART1 */
+        BOOTMEM(DEVCFG2) = 0xd979f8f9;
+        BOOTMEM(DEVCFG3) = 0xffff0722;
+        VALUE(DEVID)     = 0x04307053;      /* MX795F512L */
+        VALUE(OSCCON)    = 0x01453320;      /* external oscillator 8MHz */
+        s->sdcard_spi_port = 3;             /* SD card at SPI4, */
+        cs0_port = 4;  cs0_pin = 0;         /* select0 at E0, */
+        cs1_port = -1; cs1_pin = -1;        /* select1 not available */
+        break;
+    case BOARD_EXPLORER16:
+        /* TODO: get real data from Explorer16 board */
+        BOOTMEM(DEVCFG0) = 0xffffff7f;
+        BOOTMEM(DEVCFG1) = 0x5bfd6aff;      /* console on UART2 */
+        BOOTMEM(DEVCFG2) = 0xd979f8f9;
+        BOOTMEM(DEVCFG3) = 0xffff0722;
+        VALUE(DEVID)     = 0x04307053;      /* MX795F512L */
+        VALUE(OSCCON)    = 0x01453320;      /* external oscillator 8MHz */
+        s->sdcard_spi_port = 0;             /* SD card at SPI1, */
+        cs0_port = 1;  cs0_pin = 1;         /* select0 at B1, */
+        cs1_port = 1;  cs1_pin = 2;         /* select1 at B2 */
+        break;
+    }
+
+    /* UARTs */
+    pic32_uart_init(s, 0, PIC32_IRQ_U1E, U1STA, U1MODE);
+    pic32_uart_init(s, 1, PIC32_IRQ_U2E, U2STA, U2MODE);
+    pic32_uart_init(s, 2, PIC32_IRQ_U3E, U3STA, U3MODE);
+    pic32_uart_init(s, 3, PIC32_IRQ_U4E, U4STA, U4MODE);
+    pic32_uart_init(s, 4, PIC32_IRQ_U5E, U5STA, U5MODE);
+    pic32_uart_init(s, 5, PIC32_IRQ_U6E, U6STA, U6MODE);
+
+    /* SPIs */
+    pic32_spi_init(s, 0, PIC32_IRQ_SPI1E, SPI1CON, SPI1STAT);
+    pic32_spi_init(s, 1, PIC32_IRQ_SPI2E, SPI2CON, SPI2STAT);
+    pic32_spi_init(s, 2, PIC32_IRQ_SPI3E, SPI3CON, SPI3STAT);
+    pic32_spi_init(s, 3, PIC32_IRQ_SPI4E, SPI4CON, SPI4STAT);
+
+    /*
+     * Load SD card images.
+     * Use options:
+     *      -sd filename
+     * or   -hda filename
+     * and  -hdb filename
+     */
+    const char *sd0_file = 0, *sd1_file = 0;
+    DriveInfo *dinfo = drive_get(IF_IDE, 0, 0);
+    if (dinfo) {
+        sd0_file = qemu_opt_get(dinfo->opts, "file");
+        dinfo->is_default = 1;
+
+        dinfo = drive_get(IF_IDE, 0, 1);
+        if (dinfo) {
+            sd1_file = qemu_opt_get(dinfo->opts, "file");
+            dinfo->is_default = 1;
+        }
+    }
+    if (!sd0_file) {
+        dinfo = drive_get(IF_SD, 0, 0);
+        if (dinfo) {
+            sd0_file = qemu_opt_get(dinfo->opts, "file");
+            dinfo->is_default = 1;
+        }
+    }
+    pic32_sdcard_init(s, 0, "sd0", sd0_file, cs0_port, cs0_pin);
+    pic32_sdcard_init(s, 1, "sd1", sd1_file, cs1_port, cs1_pin);
+
+    io_reset(s);
+    pic32_sdcard_reset(s);
+    pic32_pass_signal_chars();
+}
+
+static void pic32_init_max32(MachineState *machine)
+{
+    pic32_init(machine, BOARD_MAX32);
+}
+
+static void pic32_init_maximite(MachineState *machine)
+{
+    pic32_init(machine, BOARD_MAXIMITE);
+}
+
+static void pic32_init_explorer16(MachineState *machine)
+{
+    pic32_init(machine, BOARD_EXPLORER16);
+}
+
+static int pic32_sysbus_device_init(SysBusDevice *sysbusdev)
+{
+    return 0;
+}
+
+static void pic32_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = pic32_sysbus_device_init;
+}
+
+static const TypeInfo pic32_device = {
+    .name          = TYPE_MIPS_PIC32,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(pic32_t),
+    .class_init    = pic32_class_init,
+};
+
+static void pic32_register_types(void)
+{
+    type_register_static(&pic32_device);
+}
+
+static QEMUMachine pic32_board[3] = {
+    {
+        .name       = "pic32mx7-max32",
+        .desc       = "PIC32MX7 microcontroller on chipKIT Max32 board",
+        .init       = pic32_init_max32,
+        .max_cpus   = 1,
+    },
+    {
+        .name       = "pic32mx7-maximite",
+        .desc       = "PIC32MX7 microcontroller on Geoff's Maximite board",
+        .init       = pic32_init_maximite,
+        .max_cpus   = 1,
+    },
+    {
+        .name       = "pic32mx7-explorer16",
+        .desc       = "PIC32MX7 microcontroller on Microchip Explorer-16 board",
+        .init       = pic32_init_explorer16,
+        .max_cpus   = 1,
+    },
+};
+
+static void pic32_machine_init(void)
+{
+    qemu_register_machine(&pic32_board[0]);
+    qemu_register_machine(&pic32_board[1]);
+    qemu_register_machine(&pic32_board[2]);
+}
+
+type_init(pic32_register_types)
+machine_init(pic32_machine_init);
+
+#endif /* !TARGET_MIPS64 && !TARGET_WORDS_BIGENDIAN */
diff --git a/hw/mips/mips_pic32mz.c b/hw/mips/mips_pic32mz.c
new file mode 100644
index 0000000..63086d5
--- /dev/null
+++ b/hw/mips/mips_pic32mz.c
@@ -0,0 +1,2840 @@ 
+/*
+ * QEMU support for Microchip PIC32MZ microcontroller.
+ *
+ * Copyright (c) 2015 Serge Vakulenko
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/* Only 32-bit little endian mode supported. */
+#include "config.h"
+#if !defined TARGET_MIPS64 && !defined TARGET_WORDS_BIGENDIAN
+
+#include "hw/i386/pc.h"
+#include "hw/char/serial.h"
+#include "hw/mips/cpudevs.h"
+#include "sysemu/char.h"
+#include "hw/loader.h"
+#include "qemu/error-report.h"
+#include "hw/empty_slot.h"
+#include <termios.h>
+
+#include "pic32mz.h"
+#include "pic32_peripherals.h"
+
+/* Hardware addresses */
+#define PROGRAM_FLASH_START 0x1d000000
+#define BOOT_FLASH_START    0x1fc00000
+#define DATA_MEM_START      0x00000000
+#define IO_MEM_START        0x1f800000
+
+#define PROGRAM_FLASH_SIZE  (2*1024*1024)       /* 2 Mbytes */
+#define BOOT_FLASH_SIZE     (64*1024)           /* 64 kbytes */
+#define DATA_MEM_SIZE       (512*1024)          /* 512 kbytes */
+
+#define TYPE_MIPS_PIC32     "mips-pic32mz"
+
+/*
+ * Board variants.
+ */
+enum {
+    BOARD_WIFIRE,           /* chipKIT WiFire board */
+    BOARD_MEBII,            /* Microchip MEB-II board */
+    BOARD_EXPLORER16,       /* Microchip Explorer-16 board */
+};
+
+static const char *board_name[] = {
+    "chipKIT WiFire",
+    "Microchip MEB-II",
+    "Microchip Explorer16",
+};
+
+/*
+ * Pointers to Flash memory contents.
+ */
+static char *prog_ptr;
+static char *boot_ptr;
+
+#define BOOTMEM(addr) ((uint32_t *) boot_ptr)[(addr & 0xffff) >> 2]
+
+/*
+ * TODO: add option to enable tracing.
+ */
+#define TRACE   0
+
+static void update_irq_status(pic32_t *s)
+{
+    /* Assume no interrupts pending. */
+    int cause_ripl = 0;
+    int vector = 0;
+    CPUMIPSState *env = &s->cpu->env;
+    int current_ripl = (env->CP0_Cause >> (CP0Ca_IP + 2)) & 0x3f;
+
+    VALUE(INTSTAT) = 0;
+
+    if ((VALUE(IFS0) & VALUE(IEC0)) ||
+        (VALUE(IFS1) & VALUE(IEC1)) ||
+        (VALUE(IFS2) & VALUE(IEC2)) ||
+        (VALUE(IFS3) & VALUE(IEC3)) ||
+        (VALUE(IFS4) & VALUE(IEC4)) ||
+        (VALUE(IFS5) & VALUE(IEC5)))
+    {
+        /* Find the most prioritive pending interrupt,
+         * it's vector and level. */
+        int irq;
+        for (irq = 0; irq <= PIC32_IRQ_LAST; irq++) {
+            int n = irq >> 5;
+
+            if (((VALUE(IFS(n)) & VALUE(IEC(n))) >> (irq & 31)) & 1) {
+                /* Interrupt is pending. */
+                int level = VALUE(IPC(irq >> 2));
+                level >>= 2 + (irq & 3) * 8;
+                level &= 7;
+                if (level > cause_ripl) {
+                    vector = irq;
+                    cause_ripl = level;
+                }
+            }
+        }
+        VALUE(INTSTAT) = vector | (cause_ripl << 8);
+    }
+
+    if (cause_ripl == current_ripl) {
+        return;
+    }
+
+    if (TRACE) {
+        fprintf(qemu_logfile, "--- Priority level Cause.RIPL = %u\n",
+            cause_ripl);
+    }
+
+    /*
+     * Modify Cause.RIPL field and take EIC interrupt.
+     */
+    env->CP0_Cause &= ~(0x3f << (CP0Ca_IP + 2));
+    env->CP0_Cause |= cause_ripl << (CP0Ca_IP + 2);
+    cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_HARD);
+}
+
+/*
+ * Set interrupt flag status
+ */
+static void irq_raise(pic32_t *s, int irq)
+{
+    if (VALUE(IFS(irq >> 5)) & (1 << (irq & 31))) {
+        return;
+    }
+
+    VALUE(IFS(irq >> 5)) |= 1 << (irq & 31);
+    update_irq_status(s);
+}
+
+/*
+ * Clear interrupt flag status
+ */
+static void irq_clear(pic32_t *s, int irq)
+{
+    if (!(VALUE(IFS(irq >> 5)) & (1 << (irq & 31)))) {
+        return;
+    }
+
+    VALUE(IFS(irq >> 5)) &= ~(1 << (irq & 31));
+    update_irq_status(s);
+}
+
+/*
+ * Timer interrupt.
+ */
+static void pic32_timer_irq(CPUMIPSState *env, int raise)
+{
+    pic32_t *s = env->eic_context;
+
+    if (raise) {
+        if (TRACE) {
+            fprintf(qemu_logfile, "--- %08x: Timer interrupt\n",
+                env->active_tc.PC);
+        }
+        irq_raise(s, 0);
+    } else {
+        if (TRACE) {
+            fprintf(qemu_logfile, "--- Clear timer interrupt\n");
+        }
+        irq_clear(s, 0);
+    }
+}
+
+/*
+ * Software interrupt.
+ */
+static void pic32_soft_irq(CPUMIPSState *env, int num)
+{
+    pic32_t *s = env->eic_context;
+
+    if (TRACE) {
+        fprintf(qemu_logfile, "--- %08x: Soft interrupt %u\n",
+            env->active_tc.PC, num);
+    }
+    irq_raise(s, num + 1);
+}
+
+/*
+ * Perform an assign/clear/set/invert operation.
+ */
+static inline unsigned write_op(int a, int b, int op)
+{
+    switch (op & 0xc) {
+    case 0x0:                   /* Assign */
+        a = b;
+        break;
+    case 0x4:                   /* Clear */
+        a &= ~b;
+        break;
+    case 0x8:                   /* Set */
+        a |= b;
+        break;
+    case 0xc:                   /* Invert */
+        a ^= b;
+        break;
+    }
+    return a;
+}
+
+static void io_reset(pic32_t *s)
+{
+    int i;
+
+    /*
+     * Prefetch controller.
+     */
+    VALUE(PRECON) = 0x00000007;
+
+    /*
+     * System controller.
+     */
+    s->syskey_unlock = 0;
+    VALUE(CFGCON)   = PIC32_CFGCON_ECC_DISWR | PIC32_CFGCON_TDOEN;
+    VALUE(SYSKEY)   = 0;
+    VALUE(RCON)     = 0;
+    VALUE(RSWRST)   = 0;
+    VALUE(OSCTUN)   = 0;
+    VALUE(SPLLCON)  = 0x01310201;
+    VALUE(PB1DIV)   = 0x00008801;
+    VALUE(PB2DIV)   = 0x00008801;
+    VALUE(PB3DIV)   = 0x00008801;
+    VALUE(PB4DIV)   = 0x00008801;
+    VALUE(PB5DIV)   = 0x00008801;
+    VALUE(PB7DIV)   = 0x00008800;
+    VALUE(PB8DIV)   = 0x00008801;
+
+    /*
+     * General purpose IO signals.
+     * All pins are inputs, high, open drains and pullups disabled.
+     * No interrupts on change.
+     */
+    VALUE(ANSELA)   = 0xFFFF;           /* Port A: analog select */
+    VALUE(TRISA)    = 0xFFFF;           /* Port A: mask of inputs */
+    VALUE(PORTA)    = 0xFFCF;           /* Port A: read inputs, write outputs */
+    VALUE(LATA)     = 0xFFFF;           /* Port A: read/write outputs */
+    VALUE(ODCA)     = 0;                /* Port A: open drain configuration */
+    VALUE(CNPUA)    = 0;                /* Input pin pull-up */
+    VALUE(CNPDA)    = 0;                /* Input pin pull-down */
+    VALUE(CNCONA)   = 0;                /* Interrupt-on-change control */
+    VALUE(CNENA)    = 0;                /* Input change interrupt enable */
+    VALUE(CNSTATA)  = 0;                /* Input change status */
+
+    VALUE(ANSELB)   = 0xFFFF;           /* Port B: analog select */
+    VALUE(TRISB)    = 0xFFFF;           /* Port B: mask of inputs */
+    VALUE(PORTB)    = 0xFFFF;           /* Port B: read inputs, write outputs */
+    if (s->board_type == BOARD_MEBII) {
+        VALUE(PORTB) ^= 1 << 12;        /* Disable pin RB12 - button 1 */
+    }
+    VALUE(LATB)     = 0xFFFF;           /* Port B: read/write outputs */
+    VALUE(ODCB)     = 0;                /* Port B: open drain configuration */
+    VALUE(CNPUB)    = 0;                /* Input pin pull-up */
+    VALUE(CNPDB)    = 0;                /* Input pin pull-down */
+    VALUE(CNCONB)   = 0;                /* Interrupt-on-change control */
+    VALUE(CNENB)    = 0;                /* Input change interrupt enable */
+    VALUE(CNSTATB)  = 0;                /* Input change status */
+
+    VALUE(ANSELC)   = 0xFFFF;           /* Port C: analog select */
+    VALUE(TRISC)    = 0xFFFF;           /* Port C: mask of inputs */
+    VALUE(PORTC)    = 0xFFFF;           /* Port C: read inputs, write outputs */
+    VALUE(LATC)     = 0xFFFF;           /* Port C: read/write outputs */
+    if (s->board_type == BOARD_WIFIRE) {
+        /* Disable latc[15] for the chipKIT bootloader. */
+        VALUE(LATC) ^= 0x1000;
+    }
+    VALUE(ODCC)     = 0;                /* Port C: open drain configuration */
+    VALUE(CNPUC)    = 0;                /* Input pin pull-up */
+    VALUE(CNPDC)    = 0;                /* Input pin pull-down */
+    VALUE(CNCONC)   = 0;                /* Interrupt-on-change control */
+    VALUE(CNENC)    = 0;                /* Input change interrupt enable */
+    VALUE(CNSTATC)  = 0;                /* Input change status */
+
+    VALUE(ANSELD)   = 0xFFFF;           /* Port D: analog select */
+    VALUE(TRISD)    = 0xFFFF;           /* Port D: mask of inputs */
+    VALUE(PORTD)    = 0xFFFF;           /* Port D: read inputs, write outputs */
+    VALUE(LATD)     = 0xFFFF;           /* Port D: read/write outputs */
+    VALUE(ODCD)     = 0;                /* Port D: open drain configuration */
+    VALUE(CNPUD)    = 0;                /* Input pin pull-up */
+    VALUE(CNPDD)    = 0;                /* Input pin pull-down */
+    VALUE(CNCOND)   = 0;                /* Interrupt-on-change control */
+    VALUE(CNEND)    = 0;                /* Input change interrupt enable */
+    VALUE(CNSTATD)  = 0;                /* Input change status */
+
+    VALUE(ANSELE)   = 0xFFFF;           /* Port E: analog select */
+    VALUE(TRISE)    = 0xFFFF;           /* Port E: mask of inputs */
+    VALUE(PORTE)    = 0xFFFF;           /* Port E: read inputs, write outputs */
+    VALUE(LATE)     = 0xFFFF;           /* Port E: read/write outputs */
+    VALUE(ODCE)     = 0;                /* Port E: open drain configuration */
+    VALUE(CNPUE)    = 0;                /* Input pin pull-up */
+    VALUE(CNPDE)    = 0;                /* Input pin pull-down */
+    VALUE(CNCONE)   = 0;                /* Interrupt-on-change control */
+    VALUE(CNENE)    = 0;                /* Input change interrupt enable */
+    VALUE(CNSTATE)  = 0;                /* Input change status */
+
+    VALUE(ANSELF)   = 0xFFFF;           /* Port F: analog select */
+    VALUE(TRISF)    = 0xFFFF;           /* Port F: mask of inputs */
+    VALUE(PORTF)    = 0xFFFF;           /* Port F: read inputs, write outputs */
+    VALUE(LATF)     = 0xFFFF;           /* Port F: read/write outputs */
+    VALUE(ODCF)     = 0;                /* Port F: open drain configuration */
+    VALUE(CNPUF)    = 0;                /* Input pin pull-up */
+    VALUE(CNPDF)    = 0;                /* Input pin pull-down */
+    VALUE(CNCONF)   = 0;                /* Interrupt-on-change control */
+    VALUE(CNENF)    = 0;                /* Input change interrupt enable */
+    VALUE(CNSTATF)  = 0;                /* Input change status */
+
+    VALUE(ANSELG)   = 0xFFFF;           /* Port G: analog select */
+    VALUE(TRISG)    = 0xFFFF;           /* Port G: mask of inputs */
+    VALUE(PORTG)    = 0xFFFF;           /* Port G: read inputs, write outputs */
+    VALUE(LATG)     = 0xFFFF;           /* Port G: read/write outputs */
+    VALUE(ODCG)     = 0;                /* Port G: open drain configuration */
+    VALUE(CNPUG)    = 0;                /* Input pin pull-up */
+    VALUE(CNPDG)    = 0;                /* Input pin pull-down */
+    VALUE(CNCONG)   = 0;                /* Interrupt-on-change control */
+    VALUE(CNENG)    = 0;                /* Input change interrupt enable */
+    VALUE(CNSTATG)  = 0;                /* Input change status */
+
+    VALUE(ANSELH)   = 0xFFFF;           /* Port H: analog select */
+    VALUE(TRISH)    = 0xFFFF;           /* Port H: mask of inputs */
+    VALUE(PORTH)    = 0xFFFF;           /* Port H: read inputs, write outputs */
+    VALUE(LATH)     = 0xFFFF;           /* Port H: read/write outputs */
+    VALUE(ODCH)     = 0;                /* Port H: open drain configuration */
+    VALUE(CNPUH)    = 0;                /* Input pin pull-up */
+    VALUE(CNPDH)    = 0;                /* Input pin pull-down */
+    VALUE(CNCONH)   = 0;                /* Interrupt-on-change control */
+    VALUE(CNENH)    = 0;                /* Input change interrupt enable */
+    VALUE(CNSTATH)  = 0;                /* Input change status */
+
+    VALUE(ANSELJ)   = 0xFFFF;           /* Port J: analog select */
+    VALUE(TRISJ)    = 0xFFFF;           /* Port J: mask of inputs */
+    VALUE(PORTJ)    = 0xFFFF;           /* Port J: read inputs, write outputs */
+    VALUE(LATJ)     = 0xFFFF;           /* Port J: read/write outputs */
+    VALUE(ODCJ)     = 0;                /* Port J: open drain configuration */
+    VALUE(CNPUJ)    = 0;                /* Input pin pull-up */
+    VALUE(CNPDJ)    = 0;                /* Input pin pull-down */
+    VALUE(CNCONJ)   = 0;                /* Interrupt-on-change control */
+    VALUE(CNENJ)    = 0;                /* Input change interrupt enable */
+    VALUE(CNSTATJ)  = 0;                /* Input change status */
+
+    VALUE(TRISK)    = 0xFFFF;           /* Port K: mask of inputs */
+    VALUE(PORTK)    = 0xFFFF;           /* Port K: read inputs, write outputs */
+    VALUE(LATK)     = 0xFFFF;           /* Port K: read/write outputs */
+    VALUE(ODCK)     = 0;                /* Port K: open drain configuration */
+    VALUE(CNPUK)    = 0;                /* Input pin pull-up */
+    VALUE(CNPDK)    = 0;                /* Input pin pull-down */
+    VALUE(CNCONK)   = 0;                /* Interrupt-on-change control */
+    VALUE(CNENK)    = 0;                /* Input change interrupt enable */
+    VALUE(CNSTATK)  = 0;                /* Input change status */
+
+    /*
+     * Reset UARTs.
+     */
+    VALUE(U1MODE)  = 0;
+    VALUE(U1STA)   = PIC32_USTA_RIDLE | PIC32_USTA_TRMT;
+    VALUE(U1TXREG) = 0;
+    VALUE(U1RXREG) = 0;
+    VALUE(U1BRG)   = 0;
+    VALUE(U2MODE)  = 0;
+    VALUE(U2STA)   = PIC32_USTA_RIDLE | PIC32_USTA_TRMT;
+    VALUE(U2TXREG) = 0;
+    VALUE(U2RXREG) = 0;
+    VALUE(U2BRG)   = 0;
+    VALUE(U3MODE)  = 0;
+    VALUE(U3STA)   = PIC32_USTA_RIDLE | PIC32_USTA_TRMT;
+    VALUE(U3TXREG) = 0;
+    VALUE(U3RXREG) = 0;
+    VALUE(U3BRG)   = 0;
+    VALUE(U4MODE)  = 0;
+    VALUE(U4STA)   = PIC32_USTA_RIDLE | PIC32_USTA_TRMT;
+    VALUE(U4TXREG) = 0;
+    VALUE(U4RXREG) = 0;
+    VALUE(U4BRG)   = 0;
+    VALUE(U5MODE)  = 0;
+    VALUE(U5STA)   = PIC32_USTA_RIDLE | PIC32_USTA_TRMT;
+    VALUE(U5TXREG) = 0;
+    VALUE(U5RXREG) = 0;
+    VALUE(U5BRG)   = 0;
+    VALUE(U6MODE)  = 0;
+    VALUE(U6STA)   = PIC32_USTA_RIDLE | PIC32_USTA_TRMT;
+    VALUE(U6TXREG) = 0;
+    VALUE(U6RXREG) = 0;
+    VALUE(U6BRG)   = 0;
+
+    /*
+     * Reset SPI.
+     */
+    VALUE(SPI1CON)  = 0;
+    VALUE(SPI1STAT) = PIC32_SPISTAT_SPITBE;     /* Transmit buffer is empty */
+    VALUE(SPI1BRG)  = 0;
+
+    VALUE(SPI2CON)  = 0;
+    VALUE(SPI2STAT) = PIC32_SPISTAT_SPITBE;     /* Transmit buffer is empty */
+    VALUE(SPI2BRG)  = 0;
+
+    VALUE(SPI3CON)  = 0;
+    VALUE(SPI3STAT) = PIC32_SPISTAT_SPITBE;     /* Transmit buffer is empty */
+    VALUE(SPI3BRG)  = 0;
+
+    VALUE(SPI4CON)  = 0;
+    VALUE(SPI4STAT) = PIC32_SPISTAT_SPITBE;     /* Transmit buffer is empty */
+    VALUE(SPI4BRG)  = 0;
+
+    VALUE(SPI5CON)  = 0;
+    VALUE(SPI5STAT) = PIC32_SPISTAT_SPITBE;     /* Transmit buffer is empty */
+    VALUE(SPI5BRG)  = 0;
+
+    VALUE(SPI6CON)  = 0;
+    VALUE(SPI6STAT) = PIC32_SPISTAT_SPITBE;     /* Transmit buffer is empty */
+    VALUE(SPI6BRG)  = 0;
+
+    VALUE(SPI1CON2) = 0;
+    VALUE(SPI2CON2) = 0;
+    VALUE(SPI3CON2) = 0;
+    VALUE(SPI4CON2) = 0;
+    VALUE(SPI5CON2) = 0;
+    VALUE(SPI6CON2) = 0;
+
+    for (i = 0; i < NUM_SPI; i++) {
+        s->spi[i].rfifo = 0;
+        s->spi[i].wfifo = 0;
+    }
+
+    /*
+     * Reset timers.
+     */
+    VALUE(T1CON)    = 0;
+    VALUE(TMR1)     = 0;
+    VALUE(PR1)      = 0xffff;
+    VALUE(T2CON)    = 0;
+    VALUE(TMR2)     = 0;
+    VALUE(PR2)      = 0xffff;
+    VALUE(T3CON)    = 0;
+    VALUE(TMR3)     = 0;
+    VALUE(PR3)      = 0xffff;
+    VALUE(T4CON)    = 0;
+    VALUE(TMR4)     = 0;
+    VALUE(PR4)      = 0xffff;
+    VALUE(T5CON)    = 0;
+    VALUE(TMR5)     = 0;
+    VALUE(PR5)      = 0xffff;
+    VALUE(T6CON)    = 0;
+    VALUE(TMR6)     = 0;
+    VALUE(PR6)      = 0xffff;
+    VALUE(T7CON)    = 0;
+    VALUE(TMR7)     = 0;
+    VALUE(PR7)      = 0xffff;
+    VALUE(T8CON)    = 0;
+    VALUE(TMR8)     = 0;
+    VALUE(PR8)      = 0xffff;
+    VALUE(T9CON)    = 0;
+    VALUE(TMR9)     = 0;
+    VALUE(PR9)      = 0xffff;
+
+    /*
+     * Reset Ethernet.
+     */
+    VALUE(ETHCON1)      = 0;        /* Control 1 */
+    VALUE(ETHCON2)      = 0;        /* Control 2: RX data buffer size */
+    VALUE(ETHTXST)      = 0;        /* Tx descriptor start address */
+    VALUE(ETHRXST)      = 0;        /* Rx descriptor start address */
+    VALUE(ETHHT0)       = 0;        /* Hash tasble 0 */
+    VALUE(ETHHT1)       = 0;        /* Hash tasble 1 */
+    VALUE(ETHPMM0)      = 0;        /* Pattern match mask 0 */
+    VALUE(ETHPMM1)      = 0;        /* Pattern match mask 1 */
+    VALUE(ETHPMCS)      = 0;        /* Pattern match checksum */
+    VALUE(ETHPMO)       = 0;        /* Pattern match offset */
+    VALUE(ETHRXFC)      = 0;        /* Receive filter configuration */
+    VALUE(ETHRXWM)      = 0;        /* Receive watermarks */
+    VALUE(ETHIEN)       = 0;        /* Interrupt enable */
+    VALUE(ETHIRQ)       = 0;        /* Interrupt request */
+    VALUE(ETHSTAT)      = 0;        /* Status */
+    VALUE(ETHRXOVFLOW)  = 0;        /* Receive overflow statistics */
+    VALUE(ETHFRMTXOK)   = 0;        /* Frames transmitted OK statistics */
+    VALUE(ETHSCOLFRM)   = 0;        /* Single collision frames statistics */
+    VALUE(ETHMCOLFRM)   = 0;        /* Multiple collision frames statistics */
+    VALUE(ETHFRMRXOK)   = 0;        /* Frames received OK statistics */
+    VALUE(ETHFCSERR)    = 0;        /* Frame check sequence error statistics */
+    VALUE(ETHALGNERR)   = 0;        /* Alignment errors statistics */
+    VALUE(EMAC1CFG1)    = 0x800d;   /* MAC configuration 1 */
+    VALUE(EMAC1CFG2)    = 0x4082;   /* MAC configuration 2 */
+    VALUE(EMAC1IPGT)    = 0x0012;   /* MAC back-to-back interpacket gap */
+    VALUE(EMAC1IPGR)    = 0x0c12;   /* MAC non-back-to-back interpacket gap */
+    VALUE(EMAC1CLRT)    = 0x370f;   /* MAC collision window/retry limit */
+    VALUE(EMAC1MAXF)    = 0x05ee;   /* MAC maximum frame length */
+    VALUE(EMAC1SUPP)    = 0x1000;   /* MAC PHY support */
+    VALUE(EMAC1TEST)    = 0;        /* MAC test */
+    VALUE(EMAC1MCFG)    = 0x0020;   /* MII configuration */
+    VALUE(EMAC1MCMD)    = 0;        /* MII command */
+    VALUE(EMAC1MADR)    = 0x0100;   /* MII address */
+    VALUE(EMAC1MWTD)    = 0;        /* MII write data */
+    VALUE(EMAC1MRDD)    = 0;        /* MII read data */
+    VALUE(EMAC1MIND)    = 0;        /* MII indicators */
+    VALUE(EMAC1SA0)     = 0x79c1;   /* MAC station address 0 */
+    VALUE(EMAC1SA1)     = 0xcbc0;   /* MAC station address 1 */
+    VALUE(EMAC1SA2)     = 0x1e00;   /* MAC station address 2 */
+
+    /*
+     * Reset USB.
+     */
+    VALUE(USBCSR0)      = 0x2000;
+    VALUE(USBCSR1)      = 0x00ff0000;
+    VALUE(USBCSR2)      = 0x060000fe;
+    VALUE(USBCSR3)      = 0;
+    VALUE(USBIENCSR0)   = 0;
+    VALUE(USBIENCSR1)   = 0;
+    VALUE(USBIENCSR2)   = 0;
+    VALUE(USBIENCSR3)   = 0;
+    VALUE(USBFIFO0)     = 0;
+    VALUE(USBFIFO1)     = 0;
+    VALUE(USBFIFO2)     = 0;
+    VALUE(USBFIFO3)     = 0;
+    VALUE(USBFIFO4)     = 0;
+    VALUE(USBFIFO5)     = 0;
+    VALUE(USBFIFO6)     = 0;
+    VALUE(USBFIFO7)     = 0;
+    VALUE(USBOTG)       = 0x0080;
+    VALUE(USBFIFOA)     = 0;
+    VALUE(USBHWVER)     = 0x0800;
+    VALUE(USBINFO)      = 0x3C5C8C77;
+    VALUE(USBEOFRST)    = 0x00727780;
+    VALUE(USBE0TXA)     = 0;
+    VALUE(USBE0RXA)     = 0;
+    VALUE(USBE1TXA)     = 0;
+    VALUE(USBE1RXA)     = 0;
+    VALUE(USBE2TXA)     = 0;
+    VALUE(USBE2RXA)     = 0;
+    VALUE(USBE3TXA)     = 0;
+    VALUE(USBE3RXA)     = 0;
+    VALUE(USBE4TXA)     = 0;
+    VALUE(USBE4RXA)     = 0;
+    VALUE(USBE5TXA)     = 0;
+    VALUE(USBE5RXA)     = 0;
+    VALUE(USBE6TXA)     = 0;
+    VALUE(USBE6RXA)     = 0;
+    VALUE(USBE7TXA)     = 0;
+    VALUE(USBE7RXA)     = 0;
+    VALUE(USBE0CSR0)    = 0;
+    VALUE(USBE0CSR2)    = 0;
+    VALUE(USBE0CSR3)    = 0;
+    VALUE(USBE1CSR0)    = 0;
+    VALUE(USBE1CSR1)    = 0;
+    VALUE(USBE1CSR2)    = 0;
+    VALUE(USBE1CSR3)    = 0;
+    VALUE(USBE2CSR0)    = 0;
+    VALUE(USBE2CSR1)    = 0;
+    VALUE(USBE2CSR2)    = 0;
+    VALUE(USBE2CSR3)    = 0;
+    VALUE(USBE3CSR0)    = 0;
+    VALUE(USBE3CSR1)    = 0;
+    VALUE(USBE3CSR2)    = 0;
+    VALUE(USBE3CSR3)    = 0;
+    VALUE(USBE4CSR0)    = 0;
+    VALUE(USBE4CSR1)    = 0;
+    VALUE(USBE4CSR2)    = 0;
+    VALUE(USBE4CSR3)    = 0;
+    VALUE(USBE5CSR0)    = 0;
+    VALUE(USBE5CSR1)    = 0;
+    VALUE(USBE5CSR2)    = 0;
+    VALUE(USBE5CSR3)    = 0;
+    VALUE(USBE6CSR0)    = 0;
+    VALUE(USBE6CSR1)    = 0;
+    VALUE(USBE6CSR2)    = 0;
+    VALUE(USBE6CSR3)    = 0;
+    VALUE(USBE7CSR0)    = 0;
+    VALUE(USBE7CSR1)    = 0;
+    VALUE(USBE7CSR2)    = 0;
+    VALUE(USBE7CSR3)    = 0;
+    VALUE(USBDMAINT)    = 0;
+    VALUE(USBDMA1C)     = 0;
+    VALUE(USBDMA1A)     = 0;
+    VALUE(USBDMA1N)     = 0;
+    VALUE(USBDMA2C)     = 0;
+    VALUE(USBDMA2A)     = 0;
+    VALUE(USBDMA2N)     = 0;
+    VALUE(USBDMA3C)     = 0;
+    VALUE(USBDMA3A)     = 0;
+    VALUE(USBDMA3N)     = 0;
+    VALUE(USBDMA4C)     = 0;
+    VALUE(USBDMA4A)     = 0;
+    VALUE(USBDMA4N)     = 0;
+    VALUE(USBDMA5C)     = 0;
+    VALUE(USBDMA5A)     = 0;
+    VALUE(USBDMA5N)     = 0;
+    VALUE(USBDMA6C)     = 0;
+    VALUE(USBDMA6A)     = 0;
+    VALUE(USBDMA6N)     = 0;
+    VALUE(USBDMA7C)     = 0;
+    VALUE(USBDMA7A)     = 0;
+    VALUE(USBDMA7N)     = 0;
+    VALUE(USBDMA8C)     = 0;
+    VALUE(USBDMA8A)     = 0;
+    VALUE(USBDMA8N)     = 0;
+    VALUE(USBE1RPC)     = 0;
+    VALUE(USBE2RPC)     = 0;
+    VALUE(USBE3RPC)     = 0;
+    VALUE(USBE4RPC)     = 0;
+    VALUE(USBE5RPC)     = 0;
+    VALUE(USBE6RPC)     = 0;
+    VALUE(USBE7RPC)     = 0;
+    VALUE(USBDPBFD)     = 0;
+    VALUE(USBTMCON1)    = 0x05E64074;
+    VALUE(USBTMCON2)    = 0;
+    VALUE(USBLPMR1)     = 0;
+    VALUE(USBLMPR2)     = 0;
+}
+
+static unsigned io_read32(pic32_t *s, unsigned offset, const char **namep)
+{
+    unsigned *bufp = &VALUE(offset);
+
+    switch (offset) {
+    /*-------------------------------------------------------------------------
+     * Interrupt controller registers.
+     */
+    STORAGE(INTCON); break;     /* Interrupt Control */
+    STORAGE(INTSTAT); break;    /* Interrupt Status */
+    STORAGE(IFS0); break;       /* IFS(0..2) - Interrupt Flag Status */
+    STORAGE(IFS1); break;
+    STORAGE(IFS2); break;
+    STORAGE(IFS3); break;
+    STORAGE(IFS4); break;
+    STORAGE(IFS5); break;
+    STORAGE(IEC0); break;       /* IEC(0..2) - Interrupt Enable Control */
+    STORAGE(IEC1); break;
+    STORAGE(IEC2); break;
+    STORAGE(IEC3); break;
+    STORAGE(IEC4); break;
+    STORAGE(IEC5); break;
+
+    /* IPC(0..11) - Interrupt Priority Control */
+    STORAGE(IPC0); break;       STORAGE(IPC1); break;
+    STORAGE(IPC2); break;       STORAGE(IPC3); break;
+    STORAGE(IPC4); break;       STORAGE(IPC5); break;
+    STORAGE(IPC6); break;       STORAGE(IPC7); break;
+    STORAGE(IPC8); break;       STORAGE(IPC9); break;
+    STORAGE(IPC10); break;      STORAGE(IPC11); break;
+    STORAGE(IPC12); break;      STORAGE(IPC13); break;
+    STORAGE(IPC14); break;      STORAGE(IPC15); break;
+    STORAGE(IPC16); break;      STORAGE(IPC17); break;
+    STORAGE(IPC18); break;      STORAGE(IPC19); break;
+    STORAGE(IPC20); break;      STORAGE(IPC21); break;
+    STORAGE(IPC22); break;      STORAGE(IPC23); break;
+    STORAGE(IPC24); break;      STORAGE(IPC25); break;
+    STORAGE(IPC26); break;      STORAGE(IPC27); break;
+    STORAGE(IPC28); break;      STORAGE(IPC29); break;
+    STORAGE(IPC30); break;      STORAGE(IPC31); break;
+    STORAGE(IPC32); break;      STORAGE(IPC33); break;
+    STORAGE(IPC34); break;      STORAGE(IPC35); break;
+    STORAGE(IPC36); break;      STORAGE(IPC37); break;
+    STORAGE(IPC38); break;      STORAGE(IPC39); break;
+    STORAGE(IPC40); break;      STORAGE(IPC41); break;
+    STORAGE(IPC42); break;      STORAGE(IPC43); break;
+    STORAGE(IPC44); break;      STORAGE(IPC45); break;
+    STORAGE(IPC46); break;      STORAGE(IPC47); break;
+
+    /* OFF000..OFF190 - Interrupt Vector Address Offset */
+    STORAGE(OFF(0)); break;     STORAGE(OFF(1)); break;
+    STORAGE(OFF(2)); break;     STORAGE(OFF(3)); break;
+    STORAGE(OFF(4)); break;     STORAGE(OFF(5)); break;
+    STORAGE(OFF(6)); break;     STORAGE(OFF(7)); break;
+    STORAGE(OFF(8)); break;     STORAGE(OFF(9)); break;
+    STORAGE(OFF(10)); break;    STORAGE(OFF(11)); break;
+    STORAGE(OFF(12)); break;    STORAGE(OFF(13)); break;
+    STORAGE(OFF(14)); break;    STORAGE(OFF(15)); break;
+    STORAGE(OFF(16)); break;    STORAGE(OFF(17)); break;
+    STORAGE(OFF(18)); break;    STORAGE(OFF(19)); break;
+    STORAGE(OFF(20)); break;    STORAGE(OFF(21)); break;
+    STORAGE(OFF(22)); break;    STORAGE(OFF(23)); break;
+    STORAGE(OFF(24)); break;    STORAGE(OFF(25)); break;
+    STORAGE(OFF(26)); break;    STORAGE(OFF(27)); break;
+    STORAGE(OFF(28)); break;    STORAGE(OFF(29)); break;
+    STORAGE(OFF(30)); break;    STORAGE(OFF(31)); break;
+    STORAGE(OFF(32)); break;    STORAGE(OFF(33)); break;
+    STORAGE(OFF(34)); break;    STORAGE(OFF(35)); break;
+    STORAGE(OFF(36)); break;    STORAGE(OFF(37)); break;
+    STORAGE(OFF(38)); break;    STORAGE(OFF(39)); break;
+    STORAGE(OFF(40)); break;    STORAGE(OFF(41)); break;
+    STORAGE(OFF(42)); break;    STORAGE(OFF(43)); break;
+    STORAGE(OFF(44)); break;    STORAGE(OFF(45)); break;
+    STORAGE(OFF(46)); break;    STORAGE(OFF(47)); break;
+    STORAGE(OFF(48)); break;    STORAGE(OFF(49)); break;
+    STORAGE(OFF(50)); break;    STORAGE(OFF(51)); break;
+    STORAGE(OFF(52)); break;    STORAGE(OFF(53)); break;
+    STORAGE(OFF(54)); break;    STORAGE(OFF(55)); break;
+    STORAGE(OFF(56)); break;    STORAGE(OFF(57)); break;
+    STORAGE(OFF(58)); break;    STORAGE(OFF(59)); break;
+    STORAGE(OFF(60)); break;    STORAGE(OFF(61)); break;
+    STORAGE(OFF(62)); break;    STORAGE(OFF(63)); break;
+    STORAGE(OFF(64)); break;    STORAGE(OFF(65)); break;
+    STORAGE(OFF(66)); break;    STORAGE(OFF(67)); break;
+    STORAGE(OFF(68)); break;    STORAGE(OFF(69)); break;
+    STORAGE(OFF(70)); break;    STORAGE(OFF(71)); break;
+    STORAGE(OFF(72)); break;    STORAGE(OFF(73)); break;
+    STORAGE(OFF(74)); break;    STORAGE(OFF(75)); break;
+    STORAGE(OFF(76)); break;    STORAGE(OFF(77)); break;
+    STORAGE(OFF(78)); break;    STORAGE(OFF(79)); break;
+    STORAGE(OFF(80)); break;    STORAGE(OFF(81)); break;
+    STORAGE(OFF(82)); break;    STORAGE(OFF(83)); break;
+    STORAGE(OFF(84)); break;    STORAGE(OFF(85)); break;
+    STORAGE(OFF(86)); break;    STORAGE(OFF(87)); break;
+    STORAGE(OFF(88)); break;    STORAGE(OFF(89)); break;
+    STORAGE(OFF(90)); break;    STORAGE(OFF(91)); break;
+    STORAGE(OFF(92)); break;    STORAGE(OFF(93)); break;
+    STORAGE(OFF(94)); break;    STORAGE(OFF(95)); break;
+    STORAGE(OFF(96)); break;    STORAGE(OFF(97)); break;
+    STORAGE(OFF(98)); break;    STORAGE(OFF(99)); break;
+    STORAGE(OFF(100)); break;   STORAGE(OFF(101)); break;
+    STORAGE(OFF(102)); break;   STORAGE(OFF(103)); break;
+    STORAGE(OFF(104)); break;   STORAGE(OFF(105)); break;
+    STORAGE(OFF(106)); break;   STORAGE(OFF(107)); break;
+    STORAGE(OFF(108)); break;   STORAGE(OFF(109)); break;
+    STORAGE(OFF(110)); break;   STORAGE(OFF(111)); break;
+    STORAGE(OFF(112)); break;   STORAGE(OFF(113)); break;
+    STORAGE(OFF(114)); break;   STORAGE(OFF(115)); break;
+    STORAGE(OFF(116)); break;   STORAGE(OFF(117)); break;
+    STORAGE(OFF(118)); break;   STORAGE(OFF(119)); break;
+    STORAGE(OFF(120)); break;   STORAGE(OFF(121)); break;
+    STORAGE(OFF(122)); break;   STORAGE(OFF(123)); break;
+    STORAGE(OFF(124)); break;   STORAGE(OFF(125)); break;
+    STORAGE(OFF(126)); break;   STORAGE(OFF(127)); break;
+    STORAGE(OFF(128)); break;   STORAGE(OFF(129)); break;
+    STORAGE(OFF(130)); break;   STORAGE(OFF(131)); break;
+    STORAGE(OFF(132)); break;   STORAGE(OFF(133)); break;
+    STORAGE(OFF(134)); break;   STORAGE(OFF(135)); break;
+    STORAGE(OFF(136)); break;   STORAGE(OFF(137)); break;
+    STORAGE(OFF(138)); break;   STORAGE(OFF(139)); break;
+    STORAGE(OFF(140)); break;   STORAGE(OFF(141)); break;
+    STORAGE(OFF(142)); break;   STORAGE(OFF(143)); break;
+    STORAGE(OFF(144)); break;   STORAGE(OFF(145)); break;
+    STORAGE(OFF(146)); break;   STORAGE(OFF(147)); break;
+    STORAGE(OFF(148)); break;   STORAGE(OFF(149)); break;
+    STORAGE(OFF(150)); break;   STORAGE(OFF(151)); break;
+    STORAGE(OFF(152)); break;   STORAGE(OFF(153)); break;
+    STORAGE(OFF(154)); break;   STORAGE(OFF(155)); break;
+    STORAGE(OFF(156)); break;   STORAGE(OFF(157)); break;
+    STORAGE(OFF(158)); break;   STORAGE(OFF(159)); break;
+    STORAGE(OFF(160)); break;   STORAGE(OFF(161)); break;
+    STORAGE(OFF(162)); break;   STORAGE(OFF(163)); break;
+    STORAGE(OFF(164)); break;   STORAGE(OFF(165)); break;
+    STORAGE(OFF(166)); break;   STORAGE(OFF(167)); break;
+    STORAGE(OFF(168)); break;   STORAGE(OFF(169)); break;
+    STORAGE(OFF(170)); break;   STORAGE(OFF(171)); break;
+    STORAGE(OFF(172)); break;   STORAGE(OFF(173)); break;
+    STORAGE(OFF(174)); break;   STORAGE(OFF(175)); break;
+    STORAGE(OFF(176)); break;   STORAGE(OFF(177)); break;
+    STORAGE(OFF(178)); break;   STORAGE(OFF(179)); break;
+    STORAGE(OFF(180)); break;   STORAGE(OFF(181)); break;
+    STORAGE(OFF(182)); break;   STORAGE(OFF(183)); break;
+    STORAGE(OFF(184)); break;   STORAGE(OFF(185)); break;
+    STORAGE(OFF(186)); break;   STORAGE(OFF(187)); break;
+    STORAGE(OFF(188)); break;   STORAGE(OFF(189)); break;
+    STORAGE(OFF(190)); break;
+
+    /*-------------------------------------------------------------------------
+     * Prefetch controller.
+     */
+    STORAGE(PRECON); break;     /* Prefetch Control */
+    STORAGE(PRESTAT); break;    /* Prefetch Status */
+
+    /*-------------------------------------------------------------------------
+     * System controller.
+     */
+    STORAGE(CFGCON); break;     /* Configuration Control */
+    STORAGE(DEVID); break;      /* Device Identifier */
+    STORAGE(SYSKEY); break;     /* System Key */
+    STORAGE(RCON); break;       /* Reset Control */
+    STORAGE(RSWRST);            /* Software Reset */
+        if ((VALUE(RSWRST) & 1) && s->stop_on_reset) {
+            exit(0);
+        }
+        break;
+    STORAGE(OSCCON); break;     /* Oscillator Control */
+    STORAGE(OSCTUN); break;     /* Oscillator Tuning */
+    STORAGE(SPLLCON); break;    /* System PLL Control */
+    STORAGE(REFO1CON); break;
+    STORAGE(REFO1CONCLR); *bufp = 0; break;
+    STORAGE(REFO1CONSET); *bufp = 0; break;
+    STORAGE(REFO1CONINV); *bufp = 0; break;
+    STORAGE(REFO2CON); break;
+    STORAGE(REFO2CONCLR); *bufp = 0; break;
+    STORAGE(REFO2CONSET); *bufp = 0; break;
+    STORAGE(REFO2CONINV); *bufp = 0; break;
+    STORAGE(REFO3CON); break;
+    STORAGE(REFO3CONCLR); *bufp = 0; break;
+    STORAGE(REFO3CONSET); *bufp = 0; break;
+    STORAGE(REFO3CONINV); *bufp = 0; break;
+    STORAGE(REFO4CON); break;
+    STORAGE(REFO4CONCLR); *bufp = 0; break;
+    STORAGE(REFO4CONSET); *bufp = 0; break;
+    STORAGE(REFO4CONINV); *bufp = 0; break;
+    STORAGE(PB1DIV); break;     /* Peripheral bus 1 divisor */
+    STORAGE(PB1DIVCLR); *bufp = 0; break;
+    STORAGE(PB1DIVSET); *bufp = 0; break;
+    STORAGE(PB1DIVINV); *bufp = 0; break;
+    STORAGE(PB2DIV); break;     /* Peripheral bus 2 divisor */
+    STORAGE(PB2DIVCLR); *bufp = 0; break;
+    STORAGE(PB2DIVSET); *bufp = 0; break;
+    STORAGE(PB2DIVINV); *bufp = 0; break;
+    STORAGE(PB3DIV); break;     /* Peripheral bus 3 divisor */
+    STORAGE(PB3DIVCLR); *bufp = 0; break;
+    STORAGE(PB3DIVSET); *bufp = 0; break;
+    STORAGE(PB3DIVINV); *bufp = 0; break;
+    STORAGE(PB4DIV); break;     /* Peripheral bus 4 divisor */
+    STORAGE(PB4DIVCLR); *bufp = 0; break;
+    STORAGE(PB4DIVSET); *bufp = 0; break;
+    STORAGE(PB4DIVINV); *bufp = 0; break;
+    STORAGE(PB5DIV); break;     /* Peripheral bus 5 divisor */
+    STORAGE(PB5DIVCLR); *bufp = 0; break;
+    STORAGE(PB5DIVSET); *bufp = 0; break;
+    STORAGE(PB5DIVINV); *bufp = 0; break;
+    STORAGE(PB7DIV); break;     /* Peripheral bus 7 divisor */
+    STORAGE(PB7DIVCLR); *bufp = 0; break;
+    STORAGE(PB7DIVSET); *bufp = 0; break;
+    STORAGE(PB7DIVINV); *bufp = 0; break;
+    STORAGE(PB8DIV); break;     /* Peripheral bus 8 divisor */
+    STORAGE(PB8DIVCLR); *bufp = 0; break;
+    STORAGE(PB8DIVSET); *bufp = 0; break;
+    STORAGE(PB8DIVINV); *bufp = 0; break;
+
+    /*-------------------------------------------------------------------------
+     * Peripheral port select registers: input.
+     */
+    STORAGE(INT1R); break;
+    STORAGE(INT2R); break;
+    STORAGE(INT3R); break;
+    STORAGE(INT4R); break;
+    STORAGE(T2CKR); break;
+    STORAGE(T3CKR); break;
+    STORAGE(T4CKR); break;
+    STORAGE(T5CKR); break;
+    STORAGE(T6CKR); break;
+    STORAGE(T7CKR); break;
+    STORAGE(T8CKR); break;
+    STORAGE(T9CKR); break;
+    STORAGE(IC1R); break;
+    STORAGE(IC2R); break;
+    STORAGE(IC3R); break;
+    STORAGE(IC4R); break;
+    STORAGE(IC5R); break;
+    STORAGE(IC6R); break;
+    STORAGE(IC7R); break;
+    STORAGE(IC8R); break;
+    STORAGE(IC9R); break;
+    STORAGE(OCFAR); break;
+    STORAGE(U1RXR); break;
+    STORAGE(U1CTSR); break;
+    STORAGE(U2RXR); break;
+    STORAGE(U2CTSR); break;
+    STORAGE(U3RXR); break;
+    STORAGE(U3CTSR); break;
+    STORAGE(U4RXR); break;
+    STORAGE(U4CTSR); break;
+    STORAGE(U5RXR); break;
+    STORAGE(U5CTSR); break;
+    STORAGE(U6RXR); break;
+    STORAGE(U6CTSR); break;
+    STORAGE(SDI1R); break;
+    STORAGE(SS1R); break;
+    STORAGE(SDI2R); break;
+    STORAGE(SS2R); break;
+    STORAGE(SDI3R); break;
+    STORAGE(SS3R); break;
+    STORAGE(SDI4R); break;
+    STORAGE(SS4R); break;
+    STORAGE(SDI5R); break;
+    STORAGE(SS5R); break;
+    STORAGE(SDI6R); break;
+    STORAGE(SS6R); break;
+    STORAGE(C1RXR); break;
+    STORAGE(C2RXR); break;
+    STORAGE(REFCLKI1R); break;
+    STORAGE(REFCLKI3R); break;
+    STORAGE(REFCLKI4R); break;
+
+    /*-------------------------------------------------------------------------
+     * Peripheral port select registers: output.
+     */
+    STORAGE(RPA14R); break;
+    STORAGE(RPA15R); break;
+    STORAGE(RPB0R); break;
+    STORAGE(RPB1R); break;
+    STORAGE(RPB2R); break;
+    STORAGE(RPB3R); break;
+    STORAGE(RPB5R); break;
+    STORAGE(RPB6R); break;
+    STORAGE(RPB7R); break;
+    STORAGE(RPB8R); break;
+    STORAGE(RPB9R); break;
+    STORAGE(RPB10R); break;
+    STORAGE(RPB14R); break;
+    STORAGE(RPB15R); break;
+    STORAGE(RPC1R); break;
+    STORAGE(RPC2R); break;
+    STORAGE(RPC3R); break;
+    STORAGE(RPC4R); break;
+    STORAGE(RPC13R); break;
+    STORAGE(RPC14R); break;
+    STORAGE(RPD0R); break;
+    STORAGE(RPD1R); break;
+    STORAGE(RPD2R); break;
+    STORAGE(RPD3R); break;
+    STORAGE(RPD4R); break;
+    STORAGE(RPD5R); break;
+    STORAGE(RPD6R); break;
+    STORAGE(RPD7R); break;
+    STORAGE(RPD9R); break;
+    STORAGE(RPD10R); break;
+    STORAGE(RPD11R); break;
+    STORAGE(RPD12R); break;
+    STORAGE(RPD14R); break;
+    STORAGE(RPD15R); break;
+    STORAGE(RPE3R); break;
+    STORAGE(RPE5R); break;
+    STORAGE(RPE8R); break;
+    STORAGE(RPE9R); break;
+    STORAGE(RPF0R); break;
+    STORAGE(RPF1R); break;
+    STORAGE(RPF2R); break;
+    STORAGE(RPF3R); break;
+    STORAGE(RPF4R); break;
+    STORAGE(RPF5R); break;
+    STORAGE(RPF8R); break;
+    STORAGE(RPF12R); break;
+    STORAGE(RPF13R); break;
+    STORAGE(RPG0R); break;
+    STORAGE(RPG1R); break;
+    STORAGE(RPG6R); break;
+    STORAGE(RPG7R); break;
+    STORAGE(RPG8R); break;
+    STORAGE(RPG9R); break;
+
+    /*-------------------------------------------------------------------------
+     * General purpose IO signals.
+     */
+    STORAGE(ANSELA); break;     /* Port A: analog select */
+    STORAGE(TRISA); break;      /* Port A: mask of inputs */
+    STORAGE(PORTA); break;      /* Port A: read inputs */
+    STORAGE(LATA); break;       /* Port A: read outputs */
+    STORAGE(ODCA); break;       /* Port A: open drain configuration */
+    STORAGE(CNPUA); break;      /* Input pin pull-up */
+    STORAGE(CNPDA); break;      /* Input pin pull-down */
+    STORAGE(CNCONA); break;     /* Interrupt-on-change control */
+    STORAGE(CNENA); break;      /* Input change interrupt enable */
+    STORAGE(CNSTATA); break;    /* Input change status */
+
+    STORAGE(ANSELB); break;     /* Port B: analog select */
+    STORAGE(TRISB); break;      /* Port B: mask of inputs */
+    STORAGE(PORTB); break;      /* Port B: read inputs */
+    STORAGE(LATB); break;       /* Port B: read outputs */
+    STORAGE(ODCB); break;       /* Port B: open drain configuration */
+    STORAGE(CNPUB); break;      /* Input pin pull-up */
+    STORAGE(CNPDB); break;      /* Input pin pull-down */
+    STORAGE(CNCONB); break;     /* Interrupt-on-change control */
+    STORAGE(CNENB); break;      /* Input change interrupt enable */
+    STORAGE(CNSTATB); break;    /* Input change status */
+
+    STORAGE(ANSELC); break;     /* Port C: analog select */
+    STORAGE(TRISC); break;      /* Port C: mask of inputs */
+    STORAGE(PORTC); break;      /* Port C: read inputs */
+    STORAGE(LATC); break;       /* Port C: read outputs */
+    STORAGE(ODCC); break;       /* Port C: open drain configuration */
+    STORAGE(CNPUC); break;      /* Input pin pull-up */
+    STORAGE(CNPDC); break;      /* Input pin pull-down */
+    STORAGE(CNCONC); break;     /* Interrupt-on-change control */
+    STORAGE(CNENC); break;      /* Input change interrupt enable */
+    STORAGE(CNSTATC); break;    /* Input change status */
+
+    STORAGE(ANSELD); break;     /* Port D: analog select */
+    STORAGE(TRISD); break;      /* Port D: mask of inputs */
+    STORAGE(PORTD); break;      /* Port D: read inputs */
+    STORAGE(LATD); break;       /* Port D: read outputs */
+    STORAGE(ODCD); break;       /* Port D: open drain configuration */
+    STORAGE(CNPUD); break;      /* Input pin pull-up */
+    STORAGE(CNPDD); break;      /* Input pin pull-down */
+    STORAGE(CNCOND); break;     /* Interrupt-on-change control */
+    STORAGE(CNEND); break;      /* Input change interrupt enable */
+    STORAGE(CNSTATD); break;    /* Input change status */
+
+    STORAGE(ANSELE); break;     /* Port E: analog select */
+    STORAGE(TRISE); break;      /* Port E: mask of inputs */
+    STORAGE(PORTE); break;      /* Port E: read inputs */
+    STORAGE(LATE); break;       /* Port E: read outputs */
+    STORAGE(ODCE); break;       /* Port E: open drain configuration */
+    STORAGE(CNPUE); break;      /* Input pin pull-up */
+    STORAGE(CNPDE); break;      /* Input pin pull-down */
+    STORAGE(CNCONE); break;     /* Interrupt-on-change control */
+    STORAGE(CNENE); break;      /* Input change interrupt enable */
+    STORAGE(CNSTATE); break;    /* Input change status */
+
+    STORAGE(ANSELF); break;     /* Port F: analog select */
+    STORAGE(TRISF); break;      /* Port F: mask of inputs */
+    STORAGE(PORTF); break;      /* Port F: read inputs */
+    STORAGE(LATF); break;       /* Port F: read outputs */
+    STORAGE(ODCF); break;       /* Port F: open drain configuration */
+    STORAGE(CNPUF); break;      /* Input pin pull-up */
+    STORAGE(CNPDF); break;      /* Input pin pull-down */
+    STORAGE(CNCONF); break;     /* Interrupt-on-change control */
+    STORAGE(CNENF); break;      /* Input change interrupt enable */
+    STORAGE(CNSTATF); break;    /* Input change status */
+
+    STORAGE(ANSELG); break;     /* Port G: analog select */
+    STORAGE(TRISG); break;      /* Port G: mask of inputs */
+    STORAGE(PORTG); break;      /* Port G: read inputs */
+    STORAGE(LATG); break;       /* Port G: read outputs */
+    STORAGE(ODCG); break;       /* Port G: open drain configuration */
+    STORAGE(CNPUG); break;      /* Input pin pull-up */
+    STORAGE(CNPDG); break;      /* Input pin pull-down */
+    STORAGE(CNCONG); break;     /* Interrupt-on-change control */
+    STORAGE(CNENG); break;      /* Input change interrupt enable */
+    STORAGE(CNSTATG); break;    /* Input change status */
+
+    STORAGE(ANSELH); break;     /* Port H: analog select */
+    STORAGE(TRISH); break;      /* Port H: mask of inputs */
+    STORAGE(PORTH); break;      /* Port H: read inputs */
+    STORAGE(LATH); break;       /* Port H: read outputs */
+    STORAGE(ODCH); break;       /* Port H: open drain configuration */
+    STORAGE(CNPUH); break;      /* Input pin pull-up */
+    STORAGE(CNPDH); break;      /* Input pin pull-down */
+    STORAGE(CNCONH); break;     /* Interrupt-on-change control */
+    STORAGE(CNENH); break;      /* Input change interrupt enable */
+    STORAGE(CNSTATH); break;    /* Input change status */
+
+    STORAGE(ANSELJ); break;     /* Port J: analog select */
+    STORAGE(TRISJ); break;      /* Port J: mask of inputs */
+    STORAGE(PORTJ); break;      /* Port J: read inputs */
+    STORAGE(LATJ); break;       /* Port J: read outputs */
+    STORAGE(ODCJ); break;       /* Port J: open drain configuration */
+    STORAGE(CNPUJ); break;      /* Input pin pull-up */
+    STORAGE(CNPDJ); break;      /* Input pin pull-down */
+    STORAGE(CNCONJ); break;     /* Interrupt-on-change control */
+    STORAGE(CNENJ); break;      /* Input change interrupt enable */
+    STORAGE(CNSTATJ); break;    /* Input change status */
+
+    STORAGE(TRISK); break;      /* Port K: mask of inputs */
+    STORAGE(PORTK); break;      /* Port K: read inputs */
+    STORAGE(LATK); break;       /* Port K: read outputs */
+    STORAGE(ODCK); break;       /* Port K: open drain configuration */
+    STORAGE(CNPUK); break;      /* Input pin pull-up */
+    STORAGE(CNPDK); break;      /* Input pin pull-down */
+    STORAGE(CNCONK); break;     /* Interrupt-on-change control */
+    STORAGE(CNENK); break;      /* Input change interrupt enable */
+    STORAGE(CNSTATK); break;    /* Input change status */
+
+    /*-------------------------------------------------------------------------
+     * UART 1.
+     */
+    STORAGE(U1RXREG);                           /* Receive data */
+        *bufp = pic32_uart_get_char(s, 0);
+        break;
+    STORAGE(U1BRG); break;                      /* Baud rate */
+    STORAGE(U1MODE); break;                     /* Mode */
+    STORAGE(U1STA);                             /* Status and control */
+        pic32_uart_poll_status(s, 0);
+        break;
+    STORAGE(U1TXREG);   *bufp = 0; break;       /* Transmit */
+    STORAGE(U1MODECLR); *bufp = 0; break;
+    STORAGE(U1MODESET); *bufp = 0; break;
+    STORAGE(U1MODEINV); *bufp = 0; break;
+    STORAGE(U1STACLR);  *bufp = 0; break;
+    STORAGE(U1STASET);  *bufp = 0; break;
+    STORAGE(U1STAINV);  *bufp = 0; break;
+    STORAGE(U1BRGCLR);  *bufp = 0; break;
+    STORAGE(U1BRGSET);  *bufp = 0; break;
+    STORAGE(U1BRGINV);  *bufp = 0; break;
+
+    /*-------------------------------------------------------------------------
+     * UART 2.
+     */
+    STORAGE(U2RXREG);                           /* Receive data */
+        *bufp = pic32_uart_get_char(s, 1);
+        break;
+    STORAGE(U2BRG); break;                      /* Baud rate */
+    STORAGE(U2MODE); break;                     /* Mode */
+    STORAGE(U2STA);                             /* Status and control */
+        pic32_uart_poll_status(s, 1);
+        break;
+    STORAGE(U2TXREG);   *bufp = 0; break;       /* Transmit */
+    STORAGE(U2MODECLR); *bufp = 0; break;
+    STORAGE(U2MODESET); *bufp = 0; break;
+    STORAGE(U2MODEINV); *bufp = 0; break;
+    STORAGE(U2STACLR);  *bufp = 0; break;
+    STORAGE(U2STASET);  *bufp = 0; break;
+    STORAGE(U2STAINV);  *bufp = 0; break;
+    STORAGE(U2BRGCLR);  *bufp = 0; break;
+    STORAGE(U2BRGSET);  *bufp = 0; break;
+    STORAGE(U2BRGINV);  *bufp = 0; break;
+
+    /*-------------------------------------------------------------------------
+     * UART 3.
+     */
+    STORAGE(U3RXREG);                           /* Receive data */
+        *bufp = pic32_uart_get_char(s, 2);
+        break;
+    STORAGE(U3BRG); break;                      /* Baud rate */
+    STORAGE(U3MODE); break;                     /* Mode */
+    STORAGE(U3STA);                             /* Status and control */
+        pic32_uart_poll_status(s, 2);
+        break;
+    STORAGE(U3TXREG);   *bufp = 0; break;       /* Transmit */
+    STORAGE(U3MODECLR); *bufp = 0; break;
+    STORAGE(U3MODESET); *bufp = 0; break;
+    STORAGE(U3MODEINV); *bufp = 0; break;
+    STORAGE(U3STACLR);  *bufp = 0; break;
+    STORAGE(U3STASET);  *bufp = 0; break;
+    STORAGE(U3STAINV);  *bufp = 0; break;
+    STORAGE(U3BRGCLR);  *bufp = 0; break;
+    STORAGE(U3BRGSET);  *bufp = 0; break;
+    STORAGE(U3BRGINV);  *bufp = 0; break;
+
+    /*-------------------------------------------------------------------------
+     * UART 4.
+     */
+    STORAGE(U4RXREG);                           /* Receive data */
+        *bufp = pic32_uart_get_char(s, 3);
+        break;
+    STORAGE(U4BRG); break;                      /* Baud rate */
+    STORAGE(U4MODE); break;                     /* Mode */
+    STORAGE(U4STA);                             /* Status and control */
+        pic32_uart_poll_status(s, 3);
+        break;
+    STORAGE(U4TXREG);   *bufp = 0; break;       /* Transmit */
+    STORAGE(U4MODECLR); *bufp = 0; break;
+    STORAGE(U4MODESET); *bufp = 0; break;
+    STORAGE(U4MODEINV); *bufp = 0; break;
+    STORAGE(U4STACLR);  *bufp = 0; break;
+    STORAGE(U4STASET);  *bufp = 0; break;
+    STORAGE(U4STAINV);  *bufp = 0; break;
+    STORAGE(U4BRGCLR);  *bufp = 0; break;
+    STORAGE(U4BRGSET);  *bufp = 0; break;
+    STORAGE(U4BRGINV);  *bufp = 0; break;
+
+    /*-------------------------------------------------------------------------
+     * UART 5.
+     */
+    STORAGE(U5RXREG);                           /* Receive data */
+        *bufp = pic32_uart_get_char(s, 4);
+        break;
+    STORAGE(U5BRG); break;                      /* Baud rate */
+    STORAGE(U5MODE); break;                     /* Mode */
+    STORAGE(U5STA);                             /* Status and control */
+        pic32_uart_poll_status(s, 4);
+        break;
+    STORAGE(U5TXREG);   *bufp = 0; break;       /* Transmit */
+    STORAGE(U5MODECLR); *bufp = 0; break;
+    STORAGE(U5MODESET); *bufp = 0; break;
+    STORAGE(U5MODEINV); *bufp = 0; break;
+    STORAGE(U5STACLR);  *bufp = 0; break;
+    STORAGE(U5STASET);  *bufp = 0; break;
+    STORAGE(U5STAINV);  *bufp = 0; break;
+    STORAGE(U5BRGCLR);  *bufp = 0; break;
+    STORAGE(U5BRGSET);  *bufp = 0; break;
+    STORAGE(U5BRGINV);  *bufp = 0; break;
+
+    /*-------------------------------------------------------------------------
+     * UART 6.
+     */
+    STORAGE(U6RXREG);                           /* Receive data */
+        *bufp = pic32_uart_get_char(s, 5);
+        break;
+    STORAGE(U6BRG); break;                      /* Baud rate */
+    STORAGE(U6MODE); break;                     /* Mode */
+    STORAGE(U6STA);                             /* Status and control */
+        pic32_uart_poll_status(s, 5);
+        break;
+    STORAGE(U6TXREG);   *bufp = 0; break;       /* Transmit */
+    STORAGE(U6MODECLR); *bufp = 0; break;
+    STORAGE(U6MODESET); *bufp = 0; break;
+    STORAGE(U6MODEINV); *bufp = 0; break;
+    STORAGE(U6STACLR);  *bufp = 0; break;
+    STORAGE(U6STASET);  *bufp = 0; break;
+    STORAGE(U6STAINV);  *bufp = 0; break;
+    STORAGE(U6BRGCLR);  *bufp = 0; break;
+    STORAGE(U6BRGSET);  *bufp = 0; break;
+    STORAGE(U6BRGINV);  *bufp = 0; break;
+
+    /*-------------------------------------------------------------------------
+     * SPI 1.
+     */
+    STORAGE(SPI1CON); break;                    /* Control */
+    STORAGE(SPI1CONCLR); *bufp = 0; break;
+    STORAGE(SPI1CONSET); *bufp = 0; break;
+    STORAGE(SPI1CONINV); *bufp = 0; break;
+    STORAGE(SPI1STAT); break;                   /* Status */
+    STORAGE(SPI1STATCLR); *bufp = 0; break;
+    STORAGE(SPI1STATSET); *bufp = 0; break;
+    STORAGE(SPI1STATINV); *bufp = 0; break;
+    STORAGE(SPI1BUF);                           /* Buffer */
+        *bufp = pic32_spi_readbuf(s, 0);
+        break;
+    STORAGE(SPI1BRG); break;                    /* Baud rate */
+    STORAGE(SPI1BRGCLR); *bufp = 0; break;
+    STORAGE(SPI1BRGSET); *bufp = 0; break;
+    STORAGE(SPI1BRGINV); *bufp = 0; break;
+    STORAGE(SPI1CON2); break;                   /* Control 2 */
+    STORAGE(SPI1CON2CLR); *bufp = 0; break;
+    STORAGE(SPI1CON2SET); *bufp = 0; break;
+    STORAGE(SPI1CON2INV); *bufp = 0; break;
+
+    /*-------------------------------------------------------------------------
+     * SPI 2.
+     */
+    STORAGE(SPI2CON); break;                    /* Control */
+    STORAGE(SPI2CONCLR); *bufp = 0; break;
+    STORAGE(SPI2CONSET); *bufp = 0; break;
+    STORAGE(SPI2CONINV); *bufp = 0; break;
+    STORAGE(SPI2STAT); break;                   /* Status */
+    STORAGE(SPI2STATCLR); *bufp = 0; break;
+    STORAGE(SPI2STATSET); *bufp = 0; break;
+    STORAGE(SPI2STATINV); *bufp = 0; break;
+    STORAGE(SPI2BUF);                           /* Buffer */
+        *bufp = pic32_spi_readbuf(s, 1);
+        break;
+    STORAGE(SPI2BRG); break;                    /* Baud rate */
+    STORAGE(SPI2BRGCLR); *bufp = 0; break;
+    STORAGE(SPI2BRGSET); *bufp = 0; break;
+    STORAGE(SPI2BRGINV); *bufp = 0; break;
+    STORAGE(SPI2CON2); break;                   /* Control 2 */
+    STORAGE(SPI2CON2CLR); *bufp = 0; break;
+    STORAGE(SPI2CON2SET); *bufp = 0; break;
+    STORAGE(SPI2CON2INV); *bufp = 0; break;
+
+    /*-------------------------------------------------------------------------
+     * SPI 3.
+     */
+    STORAGE(SPI3CON); break;                    /* Control */
+    STORAGE(SPI3CONCLR); *bufp = 0; break;
+    STORAGE(SPI3CONSET); *bufp = 0; break;
+    STORAGE(SPI3CONINV); *bufp = 0; break;
+    STORAGE(SPI3STAT); break;                   /* Status */
+    STORAGE(SPI3STATCLR); *bufp = 0; break;
+    STORAGE(SPI3STATSET); *bufp = 0; break;
+    STORAGE(SPI3STATINV); *bufp = 0; break;
+    STORAGE(SPI3BUF);                           /* SPIx Buffer */
+        *bufp = pic32_spi_readbuf(s, 2);
+        break;
+    STORAGE(SPI3BRG); break;                    /* Baud rate */
+    STORAGE(SPI3BRGCLR); *bufp = 0; break;
+    STORAGE(SPI3BRGSET); *bufp = 0; break;
+    STORAGE(SPI3BRGINV); *bufp = 0; break;
+    STORAGE(SPI3CON2); break;                   /* Control 2 */
+    STORAGE(SPI3CON2CLR); *bufp = 0; break;
+    STORAGE(SPI3CON2SET); *bufp = 0; break;
+    STORAGE(SPI3CON2INV); *bufp = 0; break;
+
+    /*-------------------------------------------------------------------------
+     * SPI 4.
+     */
+    STORAGE(SPI4CON); break;                    /* Control */
+    STORAGE(SPI4CONCLR); *bufp = 0; break;
+    STORAGE(SPI4CONSET); *bufp = 0; break;
+    STORAGE(SPI4CONINV); *bufp = 0; break;
+    STORAGE(SPI4STAT); break;                   /* Status */
+    STORAGE(SPI4STATCLR); *bufp = 0; break;
+    STORAGE(SPI4STATSET); *bufp = 0; break;
+    STORAGE(SPI4STATINV); *bufp = 0; break;
+    STORAGE(SPI4BUF);                           /* Buffer */
+        *bufp = pic32_spi_readbuf(s, 3);
+        break;
+    STORAGE(SPI4BRG); break;                    /* Baud rate */
+    STORAGE(SPI4BRGCLR); *bufp = 0; break;
+    STORAGE(SPI4BRGSET); *bufp = 0; break;
+    STORAGE(SPI4BRGINV); *bufp = 0; break;
+    STORAGE(SPI4CON2); break;                   /* Control 2 */
+    STORAGE(SPI4CON2CLR); *bufp = 0; break;
+    STORAGE(SPI4CON2SET); *bufp = 0; break;
+    STORAGE(SPI4CON2INV); *bufp = 0; break;
+
+    /*-------------------------------------------------------------------------
+     * Timers.
+     */
+    STORAGE(T1CON); break;
+    STORAGE(TMR1); break;
+    STORAGE(PR1); break;
+    STORAGE(T2CON); break;
+    STORAGE(TMR2); break;
+    STORAGE(PR2); break;
+    STORAGE(T3CON); break;
+    STORAGE(TMR3); break;
+    STORAGE(PR3); break;
+    STORAGE(T4CON); break;
+    STORAGE(TMR4); break;
+    STORAGE(PR4); break;
+    STORAGE(T5CON); break;
+    STORAGE(TMR5); break;
+    STORAGE(PR5); break;
+    STORAGE(T6CON); break;
+    STORAGE(TMR6); break;
+    STORAGE(PR6); break;
+    STORAGE(T7CON); break;
+    STORAGE(TMR7); break;
+    STORAGE(PR7); break;
+    STORAGE(T8CON); break;
+    STORAGE(TMR8); break;
+    STORAGE(PR8); break;
+    STORAGE(T9CON); break;
+    STORAGE(TMR9); break;
+    STORAGE(PR9); break;
+
+    /*-------------------------------------------------------------------------
+     * Ethernet.
+     */
+    STORAGE(ETHCON1); break;            /* Control 1 */
+    STORAGE(ETHCON2); break;            /* Control 2: RX data buffer size */
+    STORAGE(ETHTXST); break;            /* Tx descriptor start address */
+    STORAGE(ETHRXST); break;            /* Rx descriptor start address */
+    STORAGE(ETHHT0); break;             /* Hash tasble 0 */
+    STORAGE(ETHHT1); break;             /* Hash tasble 1 */
+    STORAGE(ETHPMM0); break;            /* Pattern match mask 0 */
+    STORAGE(ETHPMM1); break;            /* Pattern match mask 1 */
+    STORAGE(ETHPMCS); break;            /* Pattern match checksum */
+    STORAGE(ETHPMO); break;             /* Pattern match offset */
+    STORAGE(ETHRXFC); break;            /* Receive filter configuration */
+    STORAGE(ETHRXWM); break;            /* Receive watermarks */
+    STORAGE(ETHIEN); break;             /* Interrupt enable */
+    STORAGE(ETHIRQ); break;             /* Interrupt request */
+    STORAGE(ETHSTAT); break;            /* Status */
+    STORAGE(ETHRXOVFLOW); break;        /* Receive overflow statistics */
+    STORAGE(ETHFRMTXOK); break;         /* Frames transmitted OK statistics */
+    STORAGE(ETHSCOLFRM); break;         /* Single collision frames statistics */
+    STORAGE(ETHMCOLFRM); break;         /* Multiple collision statistics */
+    STORAGE(ETHFRMRXOK); break;         /* Frames received OK statistics */
+    STORAGE(ETHFCSERR); break;          /* Frame check error statistics */
+    STORAGE(ETHALGNERR); break;         /* Alignment errors statistics */
+    STORAGE(EMAC1CFG1); break;          /* MAC configuration 1 */
+    STORAGE(EMAC1CFG2); break;          /* MAC configuration 2 */
+    STORAGE(EMAC1IPGT); break;          /* MAC back-to-back interpacket gap */
+    STORAGE(EMAC1IPGR); break;          /* MAC non-back-to-back gap */
+    STORAGE(EMAC1CLRT); break;          /* MAC collision window/retry limit */
+    STORAGE(EMAC1MAXF); break;          /* MAC maximum frame length */
+    STORAGE(EMAC1SUPP); break;          /* MAC PHY support */
+    STORAGE(EMAC1TEST); break;          /* MAC test */
+    STORAGE(EMAC1MCFG); break;          /* MII configuration */
+    STORAGE(EMAC1MCMD); break;          /* MII command */
+    STORAGE(EMAC1MADR); break;          /* MII address */
+    STORAGE(EMAC1MWTD); break;          /* MII write data */
+    STORAGE(EMAC1MRDD); break;          /* MII read data */
+    STORAGE(EMAC1MIND); break;          /* MII indicators */
+    STORAGE(EMAC1SA0); break;           /* MAC station address 0 */
+    STORAGE(EMAC1SA1); break;           /* MAC station address 1 */
+    STORAGE(EMAC1SA2); break;           /* MAC station address 2 */
+
+    /*-------------------------------------------------------------------------
+     * USB.
+     */
+    STORAGE(USBCSR0); break;
+    STORAGE(USBCSR1); break;
+    STORAGE(USBCSR2); break;
+    STORAGE(USBCSR3); break;
+    STORAGE(USBIENCSR0); break;
+    STORAGE(USBIENCSR1); break;
+    STORAGE(USBIENCSR2); break;
+    STORAGE(USBIENCSR3); break;
+    STORAGE(USBFIFO0); break;
+    STORAGE(USBFIFO1); break;
+    STORAGE(USBFIFO2); break;
+    STORAGE(USBFIFO3); break;
+    STORAGE(USBFIFO4); break;
+    STORAGE(USBFIFO5); break;
+    STORAGE(USBFIFO6); break;
+    STORAGE(USBFIFO7); break;
+    STORAGE(USBOTG); break;
+    STORAGE(USBFIFOA); break;
+    STORAGE(USBHWVER); break;
+    STORAGE(USBINFO); break;
+    STORAGE(USBEOFRST); break;
+    STORAGE(USBE0TXA); break;
+    STORAGE(USBE0RXA); break;
+    STORAGE(USBE1TXA); break;
+    STORAGE(USBE1RXA); break;
+    STORAGE(USBE2TXA); break;
+    STORAGE(USBE2RXA); break;
+    STORAGE(USBE3TXA); break;
+    STORAGE(USBE3RXA); break;
+    STORAGE(USBE4TXA); break;
+    STORAGE(USBE4RXA); break;
+    STORAGE(USBE5TXA); break;
+    STORAGE(USBE5RXA); break;
+    STORAGE(USBE6TXA); break;
+    STORAGE(USBE6RXA); break;
+    STORAGE(USBE7TXA); break;
+    STORAGE(USBE7RXA); break;
+    STORAGE(USBE0CSR0); break;
+    STORAGE(USBE0CSR2); break;
+    STORAGE(USBE0CSR3); break;
+    STORAGE(USBE1CSR0); break;
+    STORAGE(USBE1CSR1); break;
+    STORAGE(USBE1CSR2); break;
+    STORAGE(USBE1CSR3); break;
+    STORAGE(USBE2CSR0); break;
+    STORAGE(USBE2CSR1); break;
+    STORAGE(USBE2CSR2); break;
+    STORAGE(USBE2CSR3); break;
+    STORAGE(USBE3CSR0); break;
+    STORAGE(USBE3CSR1); break;
+    STORAGE(USBE3CSR2); break;
+    STORAGE(USBE3CSR3); break;
+    STORAGE(USBE4CSR0); break;
+    STORAGE(USBE4CSR1); break;
+    STORAGE(USBE4CSR2); break;
+    STORAGE(USBE4CSR3); break;
+    STORAGE(USBE5CSR0); break;
+    STORAGE(USBE5CSR1); break;
+    STORAGE(USBE5CSR2); break;
+    STORAGE(USBE5CSR3); break;
+    STORAGE(USBE6CSR0); break;
+    STORAGE(USBE6CSR1); break;
+    STORAGE(USBE6CSR2); break;
+    STORAGE(USBE6CSR3); break;
+    STORAGE(USBE7CSR0); break;
+    STORAGE(USBE7CSR1); break;
+    STORAGE(USBE7CSR2); break;
+    STORAGE(USBE7CSR3); break;
+    STORAGE(USBDMAINT); break;
+    STORAGE(USBDMA1C); break;
+    STORAGE(USBDMA1A); break;
+    STORAGE(USBDMA1N); break;
+    STORAGE(USBDMA2C); break;
+    STORAGE(USBDMA2A); break;
+    STORAGE(USBDMA2N); break;
+    STORAGE(USBDMA3C); break;
+    STORAGE(USBDMA3A); break;
+    STORAGE(USBDMA3N); break;
+    STORAGE(USBDMA4C); break;
+    STORAGE(USBDMA4A); break;
+    STORAGE(USBDMA4N); break;
+    STORAGE(USBDMA5C); break;
+    STORAGE(USBDMA5A); break;
+    STORAGE(USBDMA5N); break;
+    STORAGE(USBDMA6C); break;
+    STORAGE(USBDMA6A); break;
+    STORAGE(USBDMA6N); break;
+    STORAGE(USBDMA7C); break;
+    STORAGE(USBDMA7A); break;
+    STORAGE(USBDMA7N); break;
+    STORAGE(USBDMA8C); break;
+    STORAGE(USBDMA8A); break;
+    STORAGE(USBDMA8N); break;
+    STORAGE(USBE1RPC); break;
+    STORAGE(USBE2RPC); break;
+    STORAGE(USBE3RPC); break;
+    STORAGE(USBE4RPC); break;
+    STORAGE(USBE5RPC); break;
+    STORAGE(USBE6RPC); break;
+    STORAGE(USBE7RPC); break;
+    STORAGE(USBDPBFD); break;
+    STORAGE(USBTMCON1); break;
+    STORAGE(USBTMCON2); break;
+    STORAGE(USBLPMR1); break;
+    STORAGE(USBLMPR2); break;
+
+    default:
+        printf("--- Read 1f8%05x: peripheral register not supported\n",
+            offset);
+        if (TRACE) {
+            fprintf(qemu_logfile,
+                "--- Read 1f8%05x: peripheral register not supported\n",
+                offset);
+        }
+        exit(1);
+    }
+    return *bufp;
+}
+
+static void pps_input_group1(unsigned address, unsigned data)
+{
+    /* 0000 = RPD1 */
+    /* 0001 = RPG9 */
+    /* 0010 = RPB14 */
+    /* 0011 = RPD0 */
+    /* 0101 = RPB6 */
+    /* 0110 = RPD5 */
+    /* 0111 = RPB2 */
+    /* 1000 = RPF3 */
+    /* 1001 = RPF13 */
+    /* 1011 = RPF2 */
+    /* 1100 = RPC2 */
+    /* 1101 = RPE8 */
+}
+
+static void pps_input_group2(unsigned address, unsigned data)
+{
+    /* 0000 = RPD9 */
+    /* 0001 = RPG6 */
+    /* 0010 = RPB8 */
+    /* 0011 = RPB15 */
+    /* 0100 = RPD4 */
+    /* 0101 = RPB0 */
+    /* 0110 = RPE3 */
+    /* 0111 = RPB7 */
+    /* 1001 = RPF12 */
+    /* 1010 = RPD12 */
+    /* 1011 = RPF8 */
+    /* 1100 = RPC3 */
+    /* 1101 = RPE9 */
+}
+
+static void pps_input_group3(unsigned address, unsigned data)
+{
+    /* 0000 = RPD2 */
+    /* 0001 = RPG8 */
+    /* 0010 = RPF4 */
+    /* 0011 = RPD10 */
+    /* 0100 = RPF1 */
+    /* 0101 = RPB9 */
+    /* 0110 = RPB10 */
+    /* 0111 = RPC14 */
+    /* 1000 = RPB5 */
+    /* 1010 = RPC1 */
+    /* 1011 = RPD14 */
+    /* 1100 = RPG1 */
+    /* 1101 = RPA14 */
+    /* 1110 = RPD6 */
+}
+
+static void pps_input_group4(unsigned address, unsigned data)
+{
+    /* 0000 = RPD3 */
+    /* 0001 = RPG7 */
+    /* 0010 = RPF5 */
+    /* 0011 = RPD11 */
+    /* 0100 = RPF0 */
+    /* 0101 = RPB1 */
+    /* 0110 = RPE5 */
+    /* 0111 = RPC13 */
+    /* 1000 = RPB3 */
+    /* 1010 = RPC4 */
+    /* 1011 = RPD15 */
+    /* 1100 = RPG0 */
+    /* 1101 = RPA15 */
+    /* 1110 = RPD7 */
+}
+
+static void pps_output_group1(unsigned address, unsigned data)
+{
+    /* 0000 = No Connect */
+    /* 0001 = U1TX */
+    /* 0010 = U2RTS */
+    /* 0011 = U5TX */
+    /* 0100 = U6RTS */
+    /* 0101 = SDO1 */
+    /* 0110 = SDO2 */
+    /* 0111 = SDO3 */
+    /* 1000 = SDO4 */
+    /* 1001 = SDO5 */
+    /* 1011 = OC4 */
+    /* 1100 = OC7 */
+    /* 1111 = REFCLKO1 */
+}
+
+static void pps_output_group2(unsigned address, unsigned data)
+{
+    /* 0000 = No Connect */
+    /* 0001 = U1RTS */
+    /* 0010 = U2TX */
+    /* 0011 = U5RTS */
+    /* 0100 = U6TX */
+    /* 0110 = SS2 */
+    /* 1000 = SDO4 */
+    /* 1010 = SDO6 */
+    /* 1011 = OC2 */
+    /* 1100 = OC1 */
+    /* 1101 = OC9 */
+    /* 1111 = C2TX */
+}
+
+static void pps_output_group3(unsigned address, unsigned data)
+{
+    /* 0000 = No Connect */
+    /* 0001 = U3TX */
+    /* 0010 = U4RTS */
+    /* 0101 = SDO1 */
+    /* 0110 = SDO2 */
+    /* 0111 = SDO3 */
+    /* 1001 = SDO5 */
+    /* 1010 = SS6 */
+    /* 1011 = OC3 */
+    /* 1100 = OC6 */
+    /* 1101 = REFCLKO4 */
+    /* 1110 = C2OUT */
+    /* 1111 = C1TX */
+}
+
+static void pps_output_group4(unsigned address, unsigned data)
+{
+    /* 0000 = No Connect */
+    /* 0001 = U3RTS */
+    /* 0010 = U4TX */
+    /* 0100 = U6TX */
+    /* 0101 = SS1 */
+    /* 0111 = SS3 */
+    /* 1000 = SS4 */
+    /* 1001 = SS5 */
+    /* 1010 = SDO6 */
+    /* 1011 = OC5 */
+    /* 1100 = OC8 */
+    /* 1110 = C1OUT */
+    /* 1111 = REFCLKO3 */
+}
+
+static void io_write32(pic32_t *s, unsigned offset, unsigned data,
+    const char **namep)
+{
+    unsigned *bufp = &VALUE(offset);
+    unsigned mask;
+
+    switch (offset) {
+    /*-------------------------------------------------------------------------
+     * Interrupt controller registers.
+     */
+    WRITEOP(INTCON); return;    /* Interrupt Control */
+    READONLY(INTSTAT);          /* Interrupt Status */
+    WRITEOP(IPTMR);  return;    /* Temporal Proximity Timer */
+    WRITEOP(IFS0); goto irq;    /* IFS(0..2) - Interrupt Flag Status */
+    WRITEOP(IFS1); goto irq;
+    WRITEOP(IFS2); goto irq;
+    WRITEOP(IFS3); goto irq;
+    WRITEOP(IFS4); goto irq;
+    WRITEOP(IFS5); goto irq;
+    WRITEOP(IEC0); goto irq;    /* IEC(0..2) - Interrupt Enable Control */
+    WRITEOP(IEC1); goto irq;
+    WRITEOP(IEC2); goto irq;
+    WRITEOP(IEC3); goto irq;
+    WRITEOP(IEC4); goto irq;
+    WRITEOP(IEC5); goto irq;
+
+    /* IPC(0..11) - Interrupt Priority Control */
+    WRITEOP(IPC0); goto irq;    WRITEOP(IPC1); goto irq;
+    WRITEOP(IPC2); goto irq;    WRITEOP(IPC3); goto irq;
+    WRITEOP(IPC4); goto irq;    WRITEOP(IPC5); goto irq;
+    WRITEOP(IPC6); goto irq;    WRITEOP(IPC7); goto irq;
+    WRITEOP(IPC8); goto irq;    WRITEOP(IPC9); goto irq;
+    WRITEOP(IPC10); goto irq;   WRITEOP(IPC11); goto irq;
+    WRITEOP(IPC12); goto irq;   WRITEOP(IPC13); goto irq;
+    WRITEOP(IPC14); goto irq;   WRITEOP(IPC15); goto irq;
+    WRITEOP(IPC16); goto irq;   WRITEOP(IPC17); goto irq;
+    WRITEOP(IPC18); goto irq;   WRITEOP(IPC19); goto irq;
+    WRITEOP(IPC20); goto irq;   WRITEOP(IPC21); goto irq;
+    WRITEOP(IPC22); goto irq;   WRITEOP(IPC23); goto irq;
+    WRITEOP(IPC24); goto irq;   WRITEOP(IPC25); goto irq;
+    WRITEOP(IPC26); goto irq;   WRITEOP(IPC27); goto irq;
+    WRITEOP(IPC28); goto irq;   WRITEOP(IPC29); goto irq;
+    WRITEOP(IPC30); goto irq;   WRITEOP(IPC31); goto irq;
+    WRITEOP(IPC32); goto irq;   WRITEOP(IPC33); goto irq;
+    WRITEOP(IPC34); goto irq;   WRITEOP(IPC35); goto irq;
+    WRITEOP(IPC36); goto irq;   WRITEOP(IPC37); goto irq;
+    WRITEOP(IPC38); goto irq;   WRITEOP(IPC39); goto irq;
+    WRITEOP(IPC40); goto irq;   WRITEOP(IPC41); goto irq;
+    WRITEOP(IPC42); goto irq;   WRITEOP(IPC43); goto irq;
+    WRITEOP(IPC44); goto irq;   WRITEOP(IPC45); goto irq;
+    WRITEOP(IPC46); goto irq;   WRITEOP(IPC47);
+irq:    update_irq_status(s);
+        return;
+
+    /* OFF000..OFF190 - Interrupt Vector Address Offset */
+    STORAGE(OFF(0)); break;     STORAGE(OFF(1)); break;
+    STORAGE(OFF(2)); break;     STORAGE(OFF(3)); break;
+    STORAGE(OFF(4)); break;     STORAGE(OFF(5)); break;
+    STORAGE(OFF(6)); break;     STORAGE(OFF(7)); break;
+    STORAGE(OFF(8)); break;     STORAGE(OFF(9)); break;
+    STORAGE(OFF(10)); break;    STORAGE(OFF(11)); break;
+    STORAGE(OFF(12)); break;    STORAGE(OFF(13)); break;
+    STORAGE(OFF(14)); break;    STORAGE(OFF(15)); break;
+    STORAGE(OFF(16)); break;    STORAGE(OFF(17)); break;
+    STORAGE(OFF(18)); break;    STORAGE(OFF(19)); break;
+    STORAGE(OFF(20)); break;    STORAGE(OFF(21)); break;
+    STORAGE(OFF(22)); break;    STORAGE(OFF(23)); break;
+    STORAGE(OFF(24)); break;    STORAGE(OFF(25)); break;
+    STORAGE(OFF(26)); break;    STORAGE(OFF(27)); break;
+    STORAGE(OFF(28)); break;    STORAGE(OFF(29)); break;
+    STORAGE(OFF(30)); break;    STORAGE(OFF(31)); break;
+    STORAGE(OFF(32)); break;    STORAGE(OFF(33)); break;
+    STORAGE(OFF(34)); break;    STORAGE(OFF(35)); break;
+    STORAGE(OFF(36)); break;    STORAGE(OFF(37)); break;
+    STORAGE(OFF(38)); break;    STORAGE(OFF(39)); break;
+    STORAGE(OFF(40)); break;    STORAGE(OFF(41)); break;
+    STORAGE(OFF(42)); break;    STORAGE(OFF(43)); break;
+    STORAGE(OFF(44)); break;    STORAGE(OFF(45)); break;
+    STORAGE(OFF(46)); break;    STORAGE(OFF(47)); break;
+    STORAGE(OFF(48)); break;    STORAGE(OFF(49)); break;
+    STORAGE(OFF(50)); break;    STORAGE(OFF(51)); break;
+    STORAGE(OFF(52)); break;    STORAGE(OFF(53)); break;
+    STORAGE(OFF(54)); break;    STORAGE(OFF(55)); break;
+    STORAGE(OFF(56)); break;    STORAGE(OFF(57)); break;
+    STORAGE(OFF(58)); break;    STORAGE(OFF(59)); break;
+    STORAGE(OFF(60)); break;    STORAGE(OFF(61)); break;
+    STORAGE(OFF(62)); break;    STORAGE(OFF(63)); break;
+    STORAGE(OFF(64)); break;    STORAGE(OFF(65)); break;
+    STORAGE(OFF(66)); break;    STORAGE(OFF(67)); break;
+    STORAGE(OFF(68)); break;    STORAGE(OFF(69)); break;
+    STORAGE(OFF(70)); break;    STORAGE(OFF(71)); break;
+    STORAGE(OFF(72)); break;    STORAGE(OFF(73)); break;
+    STORAGE(OFF(74)); break;    STORAGE(OFF(75)); break;
+    STORAGE(OFF(76)); break;    STORAGE(OFF(77)); break;
+    STORAGE(OFF(78)); break;    STORAGE(OFF(79)); break;
+    STORAGE(OFF(80)); break;    STORAGE(OFF(81)); break;
+    STORAGE(OFF(82)); break;    STORAGE(OFF(83)); break;
+    STORAGE(OFF(84)); break;    STORAGE(OFF(85)); break;
+    STORAGE(OFF(86)); break;    STORAGE(OFF(87)); break;
+    STORAGE(OFF(88)); break;    STORAGE(OFF(89)); break;
+    STORAGE(OFF(90)); break;    STORAGE(OFF(91)); break;
+    STORAGE(OFF(92)); break;    STORAGE(OFF(93)); break;
+    STORAGE(OFF(94)); break;    STORAGE(OFF(95)); break;
+    STORAGE(OFF(96)); break;    STORAGE(OFF(97)); break;
+    STORAGE(OFF(98)); break;    STORAGE(OFF(99)); break;
+    STORAGE(OFF(100)); break;   STORAGE(OFF(101)); break;
+    STORAGE(OFF(102)); break;   STORAGE(OFF(103)); break;
+    STORAGE(OFF(104)); break;   STORAGE(OFF(105)); break;
+    STORAGE(OFF(106)); break;   STORAGE(OFF(107)); break;
+    STORAGE(OFF(108)); break;   STORAGE(OFF(109)); break;
+    STORAGE(OFF(110)); break;   STORAGE(OFF(111)); break;
+    STORAGE(OFF(112)); break;   STORAGE(OFF(113)); break;
+    STORAGE(OFF(114)); break;   STORAGE(OFF(115)); break;
+    STORAGE(OFF(116)); break;   STORAGE(OFF(117)); break;
+    STORAGE(OFF(118)); break;   STORAGE(OFF(119)); break;
+    STORAGE(OFF(120)); break;   STORAGE(OFF(121)); break;
+    STORAGE(OFF(122)); break;   STORAGE(OFF(123)); break;
+    STORAGE(OFF(124)); break;   STORAGE(OFF(125)); break;
+    STORAGE(OFF(126)); break;   STORAGE(OFF(127)); break;
+    STORAGE(OFF(128)); break;   STORAGE(OFF(129)); break;
+    STORAGE(OFF(130)); break;   STORAGE(OFF(131)); break;
+    STORAGE(OFF(132)); break;   STORAGE(OFF(133)); break;
+    STORAGE(OFF(134)); break;   STORAGE(OFF(135)); break;
+    STORAGE(OFF(136)); break;   STORAGE(OFF(137)); break;
+    STORAGE(OFF(138)); break;   STORAGE(OFF(139)); break;
+    STORAGE(OFF(140)); break;   STORAGE(OFF(141)); break;
+    STORAGE(OFF(142)); break;   STORAGE(OFF(143)); break;
+    STORAGE(OFF(144)); break;   STORAGE(OFF(145)); break;
+    STORAGE(OFF(146)); break;   STORAGE(OFF(147)); break;
+    STORAGE(OFF(148)); break;   STORAGE(OFF(149)); break;
+    STORAGE(OFF(150)); break;   STORAGE(OFF(151)); break;
+    STORAGE(OFF(152)); break;   STORAGE(OFF(153)); break;
+    STORAGE(OFF(154)); break;   STORAGE(OFF(155)); break;
+    STORAGE(OFF(156)); break;   STORAGE(OFF(157)); break;
+    STORAGE(OFF(158)); break;   STORAGE(OFF(159)); break;
+    STORAGE(OFF(160)); break;   STORAGE(OFF(161)); break;
+    STORAGE(OFF(162)); break;   STORAGE(OFF(163)); break;
+    STORAGE(OFF(164)); break;   STORAGE(OFF(165)); break;
+    STORAGE(OFF(166)); break;   STORAGE(OFF(167)); break;
+    STORAGE(OFF(168)); break;   STORAGE(OFF(169)); break;
+    STORAGE(OFF(170)); break;   STORAGE(OFF(171)); break;
+    STORAGE(OFF(172)); break;   STORAGE(OFF(173)); break;
+    STORAGE(OFF(174)); break;   STORAGE(OFF(175)); break;
+    STORAGE(OFF(176)); break;   STORAGE(OFF(177)); break;
+    STORAGE(OFF(178)); break;   STORAGE(OFF(179)); break;
+    STORAGE(OFF(180)); break;   STORAGE(OFF(181)); break;
+    STORAGE(OFF(182)); break;   STORAGE(OFF(183)); break;
+    STORAGE(OFF(184)); break;   STORAGE(OFF(185)); break;
+    STORAGE(OFF(186)); break;   STORAGE(OFF(187)); break;
+    STORAGE(OFF(188)); break;   STORAGE(OFF(189)); break;
+    STORAGE(OFF(190)); break;
+
+    /*-------------------------------------------------------------------------
+     * Prefetch controller.
+     */
+    WRITEOP(PRECON); return;    /* Prefetch Control */
+    WRITEOP(PRESTAT); return;   /* Prefetch Status */
+
+    /*-------------------------------------------------------------------------
+     * System controller.
+     */
+    STORAGE(CFGCON);            /* Configuration Control */
+        /* TODO: use unlock sequence */
+        mask = PIC32_CFGCON_DMAPRI | PIC32_CFGCON_CPUPRI |
+            PIC32_CFGCON_ICACLK | PIC32_CFGCON_OCACLK |
+            PIC32_CFGCON_IOLOCK | PIC32_CFGCON_PMDLOCK |
+            PIC32_CFGCON_PGLOCK | PIC32_CFGCON_USBSSEN |
+            PIC32_CFGCON_ECC_MASK | PIC32_CFGCON_JTAGEN |
+            PIC32_CFGCON_TROEN | PIC32_CFGCON_TDOEN;
+        data = (data & mask) | (*bufp & ~mask);
+        break;
+    READONLY(DEVID);            /* Device Identifier */
+    STORAGE(SYSKEY);            /* System Key */
+        /* Unlock state machine. */
+        if (s->syskey_unlock == 0 && VALUE(SYSKEY) == 0xaa996655) {
+            s->syskey_unlock = 1;
+        }
+        if (s->syskey_unlock == 1 && VALUE(SYSKEY) == 0x556699aa) {
+            s->syskey_unlock = 2;
+        } else {
+            s->syskey_unlock = 0;
+        }
+        break;
+    STORAGE(RCON); break;       /* Reset Control */
+    WRITEOP(RSWRST);            /* Software Reset */
+        if (s->syskey_unlock == 2 && (VALUE(RSWRST) & 1)) {
+            /* Reset CPU. */
+            qemu_system_reset_request();
+
+            /* Reset all devices */
+            io_reset(s);
+            pic32_sdcard_reset(s);
+        }
+        break;
+    STORAGE(OSCCON); break;     /* Oscillator Control */
+    STORAGE(OSCTUN); break;     /* Oscillator Tuning */
+    STORAGE(SPLLCON); break;    /* System PLL Control */
+    WRITEOP(REFO1CON); return;
+    WRITEOP(REFO2CON); return;
+    WRITEOP(REFO3CON); return;
+    WRITEOP(REFO4CON); return;
+    WRITEOP(PB1DIV); return;    /* Peripheral bus 1 divisor */
+    WRITEOP(PB2DIV); return;    /* Peripheral bus 2 divisor */
+    WRITEOP(PB3DIV); return;    /* Peripheral bus 3 divisor */
+    WRITEOP(PB4DIV); return;    /* Peripheral bus 4 divisor */
+    WRITEOP(PB5DIV); return;    /* Peripheral bus 5 divisor */
+    WRITEOP(PB7DIV); return;    /* Peripheral bus 7 divisor */
+    WRITEOP(PB8DIV); return;    /* Peripheral bus 8 divisor */
+
+    /*-------------------------------------------------------------------------
+     * Peripheral port select registers: input.
+     */
+    STORAGE(INT1R);    pps_input_group1(offset, data); break;
+    STORAGE(T4CKR);    pps_input_group1(offset, data); break;
+    STORAGE(T9CKR);    pps_input_group1(offset, data); break;
+    STORAGE(IC1R);     pps_input_group1(offset, data); break;
+    STORAGE(IC6R);     pps_input_group1(offset, data); break;
+    STORAGE(U3CTSR);   pps_input_group1(offset, data); break;
+    STORAGE(U4RXR);    pps_input_group1(offset, data); break;
+    STORAGE(U6RXR);    pps_input_group1(offset, data); break;
+    STORAGE(SS2R);     pps_input_group1(offset, data); break;
+    STORAGE(SDI6R);    pps_input_group1(offset, data); break;
+    STORAGE(OCFAR);    pps_input_group1(offset, data); break;
+    STORAGE(REFCLKI3R); pps_input_group1(offset, data); break;
+
+    STORAGE(INT2R);    pps_input_group2(offset, data); break;
+    STORAGE(T3CKR);    pps_input_group2(offset, data); break;
+    STORAGE(T8CKR);    pps_input_group2(offset, data); break;
+    STORAGE(IC2R);     pps_input_group2(offset, data); break;
+    STORAGE(IC5R);     pps_input_group2(offset, data); break;
+    STORAGE(IC9R);     pps_input_group2(offset, data); break;
+    STORAGE(U1CTSR);   pps_input_group2(offset, data); break;
+    STORAGE(U2RXR);    pps_input_group2(offset, data); break;
+    STORAGE(U5CTSR);   pps_input_group2(offset, data); break;
+    STORAGE(SS1R);     pps_input_group2(offset, data); break;
+    STORAGE(SS3R);     pps_input_group2(offset, data); break;
+    STORAGE(SS4R);     pps_input_group2(offset, data); break;
+    STORAGE(SS5R);     pps_input_group2(offset, data); break;
+    STORAGE(C2RXR);    pps_input_group2(offset, data); break;
+
+    STORAGE(INT3R);    pps_input_group3(offset, data); break;
+    STORAGE(T2CKR);    pps_input_group3(offset, data); break;
+    STORAGE(T6CKR);    pps_input_group3(offset, data); break;
+    STORAGE(IC3R);     pps_input_group3(offset, data); break;
+    STORAGE(IC7R);     pps_input_group3(offset, data); break;
+    STORAGE(U1RXR);    pps_input_group3(offset, data); break;
+    STORAGE(U2CTSR);   pps_input_group3(offset, data); break;
+    STORAGE(U5RXR);    pps_input_group3(offset, data); break;
+    STORAGE(U6CTSR);   pps_input_group3(offset, data); break;
+    STORAGE(SDI1R);    pps_input_group3(offset, data); break;
+    STORAGE(SDI3R);    pps_input_group3(offset, data); break;
+    STORAGE(SDI5R);    pps_input_group3(offset, data); break;
+    STORAGE(SS6R);     pps_input_group3(offset, data); break;
+    STORAGE(REFCLKI1R); pps_input_group3(offset, data); break;
+
+    STORAGE(INT4R);    pps_input_group4(offset, data); break;
+    STORAGE(T5CKR);    pps_input_group4(offset, data); break;
+    STORAGE(T7CKR);    pps_input_group4(offset, data); break;
+    STORAGE(IC4R);     pps_input_group4(offset, data); break;
+    STORAGE(IC8R);     pps_input_group4(offset, data); break;
+    STORAGE(U3RXR);    pps_input_group4(offset, data); break;
+    STORAGE(U4CTSR);   pps_input_group4(offset, data); break;
+    STORAGE(SDI2R);    pps_input_group4(offset, data); break;
+    STORAGE(SDI4R);    pps_input_group4(offset, data); break;
+    STORAGE(C1RXR);    pps_input_group4(offset, data); break;
+    STORAGE(REFCLKI4R); pps_input_group4(offset, data); break;
+
+    /*-------------------------------------------------------------------------
+     * Peripheral port select registers: output.
+     */
+    STORAGE(RPA15R);   pps_output_group1(offset, data); break;
+    STORAGE(RPB1R);    pps_output_group1(offset, data); break;
+    STORAGE(RPB3R);    pps_output_group1(offset, data); break;
+    STORAGE(RPC4R);    pps_output_group1(offset, data); break;
+    STORAGE(RPC13R);   pps_output_group1(offset, data); break;
+    STORAGE(RPD3R);    pps_output_group1(offset, data); break;
+    STORAGE(RPD7R);    pps_output_group1(offset, data); break;
+    STORAGE(RPD11R);   pps_output_group1(offset, data); break;
+    STORAGE(RPD15R);   pps_output_group1(offset, data); break;
+    STORAGE(RPE5R);    pps_output_group1(offset, data); break;
+    STORAGE(RPF0R);    pps_output_group1(offset, data); break;
+    STORAGE(RPF5R);    pps_output_group1(offset, data); break;
+    STORAGE(RPG0R);    pps_output_group1(offset, data); break;
+    STORAGE(RPG7R);    pps_output_group1(offset, data); break;
+
+    STORAGE(RPB2R);    pps_output_group2(offset, data); break;
+    STORAGE(RPB6R);    pps_output_group2(offset, data); break;
+    STORAGE(RPB14R);   pps_output_group2(offset, data); break;
+    STORAGE(RPC2R);    pps_output_group2(offset, data); break;
+    STORAGE(RPD0R);    pps_output_group2(offset, data); break;
+    STORAGE(RPD1R);    pps_output_group2(offset, data); break;
+    STORAGE(RPD5R);    pps_output_group2(offset, data); break;
+    STORAGE(RPE8R);    pps_output_group2(offset, data); break;
+    STORAGE(RPF2R);    pps_output_group2(offset, data); break;
+    STORAGE(RPF3R);    pps_output_group2(offset, data); break;
+    STORAGE(RPF13R);   pps_output_group2(offset, data); break;
+    STORAGE(RPG9R);    pps_output_group2(offset, data); break;
+
+    STORAGE(RPA14R);   pps_output_group3(offset, data); break;
+    STORAGE(RPB5R);    pps_output_group3(offset, data); break;
+    STORAGE(RPB9R);    pps_output_group3(offset, data); break;
+    STORAGE(RPB10R);   pps_output_group3(offset, data); break;
+    STORAGE(RPC1R);    pps_output_group3(offset, data); break;
+    STORAGE(RPC14R);   pps_output_group3(offset, data); break;
+    STORAGE(RPD2R);    pps_output_group3(offset, data); break;
+    STORAGE(RPD6R);    pps_output_group3(offset, data); break;
+    STORAGE(RPD10R);   pps_output_group3(offset, data); break;
+    STORAGE(RPD14R);   pps_output_group3(offset, data); break;
+    STORAGE(RPF1R);    pps_output_group3(offset, data); break;
+    STORAGE(RPF4R);    pps_output_group3(offset, data); break;
+    STORAGE(RPG1R);    pps_output_group3(offset, data); break;
+    STORAGE(RPG8R);    pps_output_group3(offset, data); break;
+
+    STORAGE(RPB0R);    pps_output_group4(offset, data); break;
+    STORAGE(RPB7R);    pps_output_group4(offset, data); break;
+    STORAGE(RPB8R);    pps_output_group4(offset, data); break;
+    STORAGE(RPB15R);   pps_output_group4(offset, data); break;
+    STORAGE(RPC3R);    pps_output_group4(offset, data); break;
+    STORAGE(RPD4R);    pps_output_group4(offset, data); break;
+    STORAGE(RPD9R);    pps_output_group4(offset, data); break;
+    STORAGE(RPD12R);   pps_output_group4(offset, data); break;
+    STORAGE(RPE3R);    pps_output_group4(offset, data); break;
+    STORAGE(RPE9R);    pps_output_group4(offset, data); break;
+    STORAGE(RPF8R);    pps_output_group4(offset, data); break;
+    STORAGE(RPF12R);   pps_output_group4(offset, data); break;
+    STORAGE(RPG6R);    pps_output_group4(offset, data); break;
+
+    /*-------------------------------------------------------------------------
+     * General purpose IO signals.
+     */
+    WRITEOP(ANSELA); return;        /* Port A: analog select */
+    WRITEOP(TRISA); return;         /* Port A: mask of inputs */
+    WRITEOPX(PORTA, LATA);          /* Port A: write outputs */
+    WRITEOP(LATA);                  /* Port A: write outputs */
+        pic32_gpio_write(s, 0, VALUE(LATA));
+        return;
+    WRITEOP(ODCA); return;          /* Port A: open drain configuration */
+    WRITEOP(CNPUA); return;         /* Input pin pull-up */
+    WRITEOP(CNPDA); return;         /* Input pin pull-down */
+    WRITEOP(CNCONA); return;        /* Interrupt-on-change control */
+    WRITEOP(CNENA); return;         /* Input change interrupt enable */
+    WRITEOP(CNSTATA); return;       /* Input change status */
+
+    WRITEOP(ANSELB); return;        /* Port B: analog select */
+    WRITEOP(TRISB); return;         /* Port B: mask of inputs */
+    WRITEOPX(PORTB, LATB);          /* Port B: write outputs */
+    WRITEOP(LATB);                  /* Port B: write outputs */
+        pic32_gpio_write(s, 1, VALUE(LATB));
+        return;
+    WRITEOP(ODCB); return;          /* Port B: open drain configuration */
+    WRITEOP(CNPUB); return;         /* Input pin pull-up */
+    WRITEOP(CNPDB); return;         /* Input pin pull-down */
+    WRITEOP(CNCONB); return;        /* Interrupt-on-change control */
+    WRITEOP(CNENB); return;         /* Input change interrupt enable */
+    WRITEOP(CNSTATB); return;       /* Input change status */
+
+    WRITEOP(ANSELC); return;        /* Port C: analog select */
+    WRITEOP(TRISC); return;         /* Port C: mask of inputs */
+    WRITEOPX(PORTC, LATC);          /* Port C: write outputs */
+    WRITEOP(LATC);                  /* Port C: write outputs */
+        pic32_gpio_write(s, 2, VALUE(LATC));
+        return;
+    WRITEOP(ODCC); return;          /* Port C: open drain configuration */
+    WRITEOP(CNPUC); return;         /* Input pin pull-up */
+    WRITEOP(CNPDC); return;         /* Input pin pull-down */
+    WRITEOP(CNCONC); return;        /* Interrupt-on-change control */
+    WRITEOP(CNENC); return;         /* Input change interrupt enable */
+    WRITEOP(CNSTATC); return;       /* Input change status */
+
+    WRITEOP(ANSELD); return;        /* Port D: analog select */
+    WRITEOP(TRISD); return;         /* Port D: mask of inputs */
+    WRITEOPX(PORTD, LATD);          /* Port D: write outputs */
+    WRITEOP(LATD);                  /* Port D: write outputs */
+        pic32_gpio_write(s, 3, VALUE(LATD));
+        return;
+    WRITEOP(ODCD); return;          /* Port D: open drain configuration */
+    WRITEOP(CNPUD); return;         /* Input pin pull-up */
+    WRITEOP(CNPDD); return;         /* Input pin pull-down */
+    WRITEOP(CNCOND); return;        /* Interrupt-on-change control */
+    WRITEOP(CNEND); return;         /* Input change interrupt enable */
+    WRITEOP(CNSTATD); return;       /* Input change status */
+
+    WRITEOP(ANSELE); return;        /* Port E: analog select */
+    WRITEOP(TRISE); return;         /* Port E: mask of inputs */
+    WRITEOPX(PORTE, LATE);          /* Port E: write outputs */
+    WRITEOP(LATE);                  /* Port E: write outputs */
+        pic32_gpio_write(s, 4, VALUE(LATE));
+        return;
+    WRITEOP(ODCE); return;          /* Port E: open drain configuration */
+    WRITEOP(CNPUE); return;         /* Input pin pull-up */
+    WRITEOP(CNPDE); return;         /* Input pin pull-down */
+    WRITEOP(CNCONE); return;        /* Interrupt-on-change control */
+    WRITEOP(CNENE); return;         /* Input change interrupt enable */
+    WRITEOP(CNSTATE); return;       /* Input change status */
+
+    WRITEOP(ANSELF); return;        /* Port F: analog select */
+    WRITEOP(TRISF); return;         /* Port F: mask of inputs */
+    WRITEOPX(PORTF, LATF);          /* Port F: write outputs */
+    WRITEOP(LATF);                  /* Port F: write outputs */
+        pic32_gpio_write(s, 5, VALUE(LATF));
+        return;
+    WRITEOP(ODCF); return;          /* Port F: open drain configuration */
+    WRITEOP(CNPUF); return;         /* Input pin pull-up */
+    WRITEOP(CNPDF); return;         /* Input pin pull-down */
+    WRITEOP(CNCONF); return;        /* Interrupt-on-change control */
+    WRITEOP(CNENF); return;         /* Input change interrupt enable */
+    WRITEOP(CNSTATF); return;       /* Input change status */
+
+    WRITEOP(ANSELG); return;        /* Port G: analog select */
+    WRITEOP(TRISG); return;         /* Port G: mask of inputs */
+    WRITEOPX(PORTG, LATG);          /* Port G: write outputs */
+    WRITEOP(LATG);                  /* Port G: write outputs */
+        pic32_gpio_write(s, 6, VALUE(LATG));
+        return;
+    WRITEOP(ODCG); return;          /* Port G: open drain configuration */
+    WRITEOP(CNPUG); return;         /* Input pin pull-up */
+    WRITEOP(CNPDG); return;         /* Input pin pull-down */
+    WRITEOP(CNCONG); return;        /* Interrupt-on-change control */
+    WRITEOP(CNENG); return;         /* Input change interrupt enable */
+    WRITEOP(CNSTATG); return;       /* Input change status */
+
+    WRITEOP(ANSELH); return;        /* Port H: analog select */
+    WRITEOP(TRISH); return;         /* Port H: mask of inputs */
+    WRITEOPX(PORTH, LATH);          /* Port H: write outputs */
+    WRITEOP(LATH);                  /* Port H: write outputs */
+        pic32_gpio_write(s, 7, VALUE(LATH));
+        return;
+    WRITEOP(ODCH); return;          /* Port H: open drain configuration */
+    WRITEOP(CNPUH); return;         /* Input pin pull-up */
+    WRITEOP(CNPDH); return;         /* Input pin pull-down */
+    WRITEOP(CNCONH); return;        /* Interrupt-on-change control */
+    WRITEOP(CNENH); return;         /* Input change interrupt enable */
+    WRITEOP(CNSTATH); return;       /* Input change status */
+
+    WRITEOP(ANSELJ); return;        /* Port J: analog select */
+    WRITEOP(TRISJ); return;         /* Port J: mask of inputs */
+    WRITEOPX(PORTJ, LATJ);          /* Port J: write outputs */
+    WRITEOP(LATJ);                  /* Port J: write outputs */
+        pic32_gpio_write(s, 8, VALUE(LATJ));
+        return;
+    WRITEOP(ODCJ); return;          /* Port J: open drain configuration */
+    WRITEOP(CNPUJ); return;         /* Input pin pull-up */
+    WRITEOP(CNPDJ); return;         /* Input pin pull-down */
+    WRITEOP(CNCONJ); return;        /* Interrupt-on-change control */
+    WRITEOP(CNENJ); return;         /* Input change interrupt enable */
+    WRITEOP(CNSTATJ); return;       /* Input change status */
+
+    WRITEOP(TRISK); return;         /* Port K: mask of inputs */
+    WRITEOPX(PORTK, LATK);          /* Port K: write outputs */
+    WRITEOP(LATK);                  /* Port K: write outputs */
+        pic32_gpio_write(s, 9, VALUE(LATK));
+        return;
+    WRITEOP(ODCK); return;          /* Port K: open drain configuration */
+    WRITEOP(CNPUK); return;         /* Input pin pull-up */
+    WRITEOP(CNPDK); return;         /* Input pin pull-down */
+    WRITEOP(CNCONK); return;        /* Interrupt-on-change control */
+    WRITEOP(CNENK); return;         /* Input change interrupt enable */
+    WRITEOP(CNSTATK); return;       /* Input change status */
+
+    /*-------------------------------------------------------------------------
+     * UART 1.
+     */
+    STORAGE(U1TXREG);                               /* Transmit */
+        pic32_uart_put_char(s, 0, data);
+        break;
+    WRITEOP(U1MODE);                                /* Mode */
+        pic32_uart_update_mode(s, 0);
+        return;
+    WRITEOPR(U1STA,                                 /* Status and control */
+        PIC32_USTA_URXDA | PIC32_USTA_FERR | PIC32_USTA_PERR |
+        PIC32_USTA_RIDLE | PIC32_USTA_TRMT | PIC32_USTA_UTXBF);
+        pic32_uart_update_status(s, 0);
+        return;
+    WRITEOP(U1BRG); return;                         /* Baud rate */
+    READONLY(U1RXREG);                              /* Receive */
+
+    /*-------------------------------------------------------------------------
+     * UART 2.
+     */
+    STORAGE(U2TXREG);                               /* Transmit */
+        pic32_uart_put_char(s, 1, data);
+        break;
+    WRITEOP(U2MODE);                                /* Mode */
+        pic32_uart_update_mode(s, 1);
+        return;
+    WRITEOPR(U2STA,                                 /* Status and control */
+        PIC32_USTA_URXDA | PIC32_USTA_FERR | PIC32_USTA_PERR |
+        PIC32_USTA_RIDLE | PIC32_USTA_TRMT | PIC32_USTA_UTXBF);
+        pic32_uart_update_status(s, 1);
+        return;
+    WRITEOP(U2BRG); return;                         /* Baud rate */
+    READONLY(U2RXREG);                              /* Receive */
+
+    /*-------------------------------------------------------------------------
+     * UART 3.
+     */
+    STORAGE(U3TXREG);                               /* Transmit */
+        pic32_uart_put_char(s, 2, data);
+        break;
+    WRITEOP(U3MODE);                                /* Mode */
+        pic32_uart_update_mode(s, 2);
+        return;
+    WRITEOPR(U3STA,                                 /* Status and control */
+        PIC32_USTA_URXDA | PIC32_USTA_FERR | PIC32_USTA_PERR |
+        PIC32_USTA_RIDLE | PIC32_USTA_TRMT | PIC32_USTA_UTXBF);
+        pic32_uart_update_status(s, 2);
+        return;
+    WRITEOP(U3BRG); return;                         /* Baud rate */
+    READONLY(U3RXREG);                              /* Receive */
+
+    /*-------------------------------------------------------------------------
+     * UART 4.
+     */
+    STORAGE(U4TXREG);                               /* Transmit */
+        pic32_uart_put_char(s, 3, data);
+        break;
+    WRITEOP(U4MODE);                                /* Mode */
+        pic32_uart_update_mode(s, 3);
+        return;
+    WRITEOPR(U4STA,                                 /* Status and control */
+        PIC32_USTA_URXDA | PIC32_USTA_FERR | PIC32_USTA_PERR |
+        PIC32_USTA_RIDLE | PIC32_USTA_TRMT | PIC32_USTA_UTXBF);
+        pic32_uart_update_status(s, 3);
+        return;
+    WRITEOP(U4BRG); return;                         /* Baud rate */
+    READONLY(U4RXREG);                              /* Receive */
+
+    /*-------------------------------------------------------------------------
+     * UART 5.
+     */
+    STORAGE(U5TXREG);                               /* Transmit */
+        pic32_uart_put_char(s, 4, data);
+        break;
+    WRITEOP(U5MODE);                                /* Mode */
+        pic32_uart_update_mode(s, 4);
+        return;
+    WRITEOPR(U5STA,                                 /* Status and control */
+        PIC32_USTA_URXDA | PIC32_USTA_FERR | PIC32_USTA_PERR |
+        PIC32_USTA_RIDLE | PIC32_USTA_TRMT | PIC32_USTA_UTXBF);
+        pic32_uart_update_status(s, 4);
+        return;
+    WRITEOP(U5BRG); return;                         /* Baud rate */
+    READONLY(U5RXREG);                              /* Receive */
+
+    /*-------------------------------------------------------------------------
+     * UART 6.
+     */
+    STORAGE(U6TXREG);                               /* Transmit */
+        pic32_uart_put_char(s, 5, data);
+        break;
+    WRITEOP(U6MODE);                                /* Mode */
+        pic32_uart_update_mode(s, 5);
+        return;
+    WRITEOPR(U6STA,                                 /* Status and control */
+        PIC32_USTA_URXDA | PIC32_USTA_FERR | PIC32_USTA_PERR |
+        PIC32_USTA_RIDLE | PIC32_USTA_TRMT | PIC32_USTA_UTXBF);
+        pic32_uart_update_status(s, 5);
+        return;
+    WRITEOP(U6BRG); return;                         /* Baud rate */
+    READONLY(U6RXREG);                              /* Receive */
+
+    /*-------------------------------------------------------------------------
+     * SPI.
+     */
+    WRITEOP(SPI1CON);                               /* Control */
+        pic32_spi_control(s, 0);
+        return;
+    WRITEOPR(SPI1STAT, ~PIC32_SPISTAT_SPIROV);      /* Status */
+        return;                                     /* Only ROV bit writable */
+    STORAGE(SPI1BUF);                               /* Buffer */
+        pic32_spi_writebuf(s, 0, data);
+        return;
+    WRITEOP(SPI1BRG); return;                       /* Baud rate */
+    WRITEOP(SPI1CON2); return;                      /* Control 2 */
+
+    WRITEOP(SPI2CON);                               /* Control */
+        pic32_spi_control(s, 1);
+        return;
+    WRITEOPR(SPI2STAT, ~PIC32_SPISTAT_SPIROV);      /* Status */
+        return;                                     /* Only ROV bit writable */
+    STORAGE(SPI2BUF);                               /* Buffer */
+        pic32_spi_writebuf(s, 1, data);
+        return;
+    WRITEOP(SPI2BRG); return;                       /* Baud rate */
+    WRITEOP(SPI2CON2); return;                      /* Control 2 */
+
+    WRITEOP(SPI3CON);                               /* Control */
+        pic32_spi_control(s, 2);
+        return;
+    WRITEOPR(SPI3STAT, ~PIC32_SPISTAT_SPIROV);      /* Status */
+        return;                                     /* Only ROV bit writable */
+    STORAGE(SPI3BUF);                               /* Buffer */
+        pic32_spi_writebuf(s, 2, data);
+        return;
+    WRITEOP(SPI3BRG); return;                       /* Baud rate */
+    WRITEOP(SPI3CON2); return;                      /* Control 2 */
+
+    WRITEOP(SPI4CON);                               /* Control */
+        pic32_spi_control(s, 3);
+        return;
+    WRITEOPR(SPI4STAT, ~PIC32_SPISTAT_SPIROV);      /* Status */
+        return;                                     /* Only ROV bit writable */
+    STORAGE(SPI4BUF);                               /* Buffer */
+        pic32_spi_writebuf(s, 3, data);
+        return;
+    WRITEOP(SPI4BRG); return;                       /* Baud rate */
+    WRITEOP(SPI4CON2); return;                      /* Control 2 */
+
+    /*
+     * Timers 1-9.
+     */
+    WRITEOP(T1CON); return;
+    WRITEOP(TMR1); return;
+    WRITEOP(PR1); return;
+    WRITEOP(T2CON); return;
+    WRITEOP(TMR2); return;
+    WRITEOP(PR2); return;
+    WRITEOP(T3CON); return;
+    WRITEOP(TMR3); return;
+    WRITEOP(PR3); return;
+    WRITEOP(T4CON); return;
+    WRITEOP(TMR4); return;
+    WRITEOP(PR4); return;
+    WRITEOP(T5CON); return;
+    WRITEOP(TMR5); return;
+    WRITEOP(PR5); return;
+    WRITEOP(T6CON); return;
+    WRITEOP(TMR6); return;
+    WRITEOP(PR6); return;
+    WRITEOP(T7CON); return;
+    WRITEOP(TMR7); return;
+    WRITEOP(PR7); return;
+    WRITEOP(T8CON); return;
+    WRITEOP(TMR8); return;
+    WRITEOP(PR8); return;
+    WRITEOP(T9CON); return;
+    WRITEOP(TMR9); return;
+    WRITEOP(PR9); return;
+
+    /*-------------------------------------------------------------------------
+     * Ethernet.
+     */
+    WRITEOP(ETHCON1);                   /* Control 1 */
+        pic32_eth_control(s);
+        return;
+    WRITEOP(ETHCON2); return;           /* Control 2: RX data buffer size */
+    WRITEOP(ETHTXST); return;           /* Tx descriptor start address */
+    WRITEOP(ETHRXST); return;           /* Rx descriptor start address */
+    WRITEOP(ETHHT0); return;            /* Hash tasble 0 */
+    WRITEOP(ETHHT1); return;            /* Hash tasble 1 */
+    WRITEOP(ETHPMM0); return;           /* Pattern match mask 0 */
+    WRITEOP(ETHPMM1); return;           /* Pattern match mask 1 */
+    WRITEOP(ETHPMCS); return;           /* Pattern match checksum */
+    WRITEOP(ETHPMO); return;            /* Pattern match offset */
+    WRITEOP(ETHRXFC); return;           /* Receive filter configuration */
+    WRITEOP(ETHRXWM); return;           /* Receive watermarks */
+    WRITEOP(ETHIEN); return;            /* Interrupt enable */
+    WRITEOP(ETHIRQ); return;            /* Interrupt request */
+    STORAGE(ETHSTAT); break;            /* Status */
+    WRITEOP(ETHRXOVFLOW); return;       /* Receive overflow statistics */
+    WRITEOP(ETHFRMTXOK); return;        /* Frames transmitted OK statistics */
+    WRITEOP(ETHSCOLFRM); return;        /* Single collision frames statistics */
+    WRITEOP(ETHMCOLFRM); return;        /* Multiple collision statistics */
+    WRITEOP(ETHFRMRXOK); return;        /* Frames received OK statistics */
+    WRITEOP(ETHFCSERR); return;         /* Frame check sequence statistics */
+    WRITEOP(ETHALGNERR); return;        /* Alignment errors statistics */
+    WRITEOP(EMAC1CFG1); return;         /* MAC configuration 1 */
+    WRITEOP(EMAC1CFG2); return;         /* MAC configuration 2 */
+    WRITEOP(EMAC1IPGT); return;         /* MAC back-to-back interpacket gap */
+    WRITEOP(EMAC1IPGR); return;         /* MAC non-back-to-back gap */
+    WRITEOP(EMAC1CLRT); return;         /* MAC collision window/retry limit */
+    WRITEOP(EMAC1MAXF); return;         /* MAC maximum frame length */
+    WRITEOP(EMAC1SUPP); return;         /* MAC PHY support */
+    WRITEOP(EMAC1TEST); return;         /* MAC test */
+    WRITEOP(EMAC1MCFG); return;         /* MII configuration */
+    WRITEOP(EMAC1MCMD);                 /* MII command */
+        pic32_mii_command(s);
+        return;
+    WRITEOP(EMAC1MADR); return;         /* MII address */
+    WRITEOP(EMAC1MWTD);                 /* MII write data */
+        pic32_mii_write(s);
+        return;
+    WRITEOP(EMAC1MRDD); return;         /* MII read data */
+    WRITEOP(EMAC1MIND); return;         /* MII indicators */
+    WRITEOP(EMAC1SA0); return;          /* MAC station address 0 */
+    WRITEOP(EMAC1SA1); return;          /* MAC station address 1 */
+    WRITEOP(EMAC1SA2); return;          /* MAC station address 2 */
+
+    /*-------------------------------------------------------------------------
+     * USB.
+     */
+    STORAGE(USBCSR0); break;
+    STORAGE(USBCSR1); break;
+    STORAGE(USBCSR2); break;
+    STORAGE(USBCSR3); break;
+    STORAGE(USBIENCSR0); break;
+    STORAGE(USBIENCSR1); break;
+    STORAGE(USBIENCSR2); break;
+    STORAGE(USBIENCSR3); break;
+    STORAGE(USBFIFO0); break;
+    STORAGE(USBFIFO1); break;
+    STORAGE(USBFIFO2); break;
+    STORAGE(USBFIFO3); break;
+    STORAGE(USBFIFO4); break;
+    STORAGE(USBFIFO5); break;
+    STORAGE(USBFIFO6); break;
+    STORAGE(USBFIFO7); break;
+    STORAGE(USBOTG); break;
+    STORAGE(USBFIFOA); break;
+    STORAGE(USBHWVER); break;
+    STORAGE(USBINFO); break;
+    STORAGE(USBEOFRST); break;
+    STORAGE(USBE0TXA); break;
+    STORAGE(USBE0RXA); break;
+    STORAGE(USBE1TXA); break;
+    STORAGE(USBE1RXA); break;
+    STORAGE(USBE2TXA); break;
+    STORAGE(USBE2RXA); break;
+    STORAGE(USBE3TXA); break;
+    STORAGE(USBE3RXA); break;
+    STORAGE(USBE4TXA); break;
+    STORAGE(USBE4RXA); break;
+    STORAGE(USBE5TXA); break;
+    STORAGE(USBE5RXA); break;
+    STORAGE(USBE6TXA); break;
+    STORAGE(USBE6RXA); break;
+    STORAGE(USBE7TXA); break;
+    STORAGE(USBE7RXA); break;
+    STORAGE(USBE0CSR0); break;
+    STORAGE(USBE0CSR2); break;
+    STORAGE(USBE0CSR3); break;
+    STORAGE(USBE1CSR0); break;
+    STORAGE(USBE1CSR1); break;
+    STORAGE(USBE1CSR2); break;
+    STORAGE(USBE1CSR3); break;
+    STORAGE(USBE2CSR0); break;
+    STORAGE(USBE2CSR1); break;
+    STORAGE(USBE2CSR2); break;
+    STORAGE(USBE2CSR3); break;
+    STORAGE(USBE3CSR0); break;
+    STORAGE(USBE3CSR1); break;
+    STORAGE(USBE3CSR2); break;
+    STORAGE(USBE3CSR3); break;
+    STORAGE(USBE4CSR0); break;
+    STORAGE(USBE4CSR1); break;
+    STORAGE(USBE4CSR2); break;
+    STORAGE(USBE4CSR3); break;
+    STORAGE(USBE5CSR0); break;
+    STORAGE(USBE5CSR1); break;
+    STORAGE(USBE5CSR2); break;
+    STORAGE(USBE5CSR3); break;
+    STORAGE(USBE6CSR0); break;
+    STORAGE(USBE6CSR1); break;
+    STORAGE(USBE6CSR2); break;
+    STORAGE(USBE6CSR3); break;
+    STORAGE(USBE7CSR0); break;
+    STORAGE(USBE7CSR1); break;
+    STORAGE(USBE7CSR2); break;
+    STORAGE(USBE7CSR3); break;
+    STORAGE(USBDMAINT); break;
+    STORAGE(USBDMA1C); break;
+    STORAGE(USBDMA1A); break;
+    STORAGE(USBDMA1N); break;
+    STORAGE(USBDMA2C); break;
+    STORAGE(USBDMA2A); break;
+    STORAGE(USBDMA2N); break;
+    STORAGE(USBDMA3C); break;
+    STORAGE(USBDMA3A); break;
+    STORAGE(USBDMA3N); break;
+    STORAGE(USBDMA4C); break;
+    STORAGE(USBDMA4A); break;
+    STORAGE(USBDMA4N); break;
+    STORAGE(USBDMA5C); break;
+    STORAGE(USBDMA5A); break;
+    STORAGE(USBDMA5N); break;
+    STORAGE(USBDMA6C); break;
+    STORAGE(USBDMA6A); break;
+    STORAGE(USBDMA6N); break;
+    STORAGE(USBDMA7C); break;
+    STORAGE(USBDMA7A); break;
+    STORAGE(USBDMA7N); break;
+    STORAGE(USBDMA8C); break;
+    STORAGE(USBDMA8A); break;
+    STORAGE(USBDMA8N); break;
+    STORAGE(USBE1RPC); break;
+    STORAGE(USBE2RPC); break;
+    STORAGE(USBE3RPC); break;
+    STORAGE(USBE4RPC); break;
+    STORAGE(USBE5RPC); break;
+    STORAGE(USBE6RPC); break;
+    STORAGE(USBE7RPC); break;
+    STORAGE(USBDPBFD); break;
+    STORAGE(USBTMCON1); break;
+    STORAGE(USBTMCON2); break;
+    STORAGE(USBLPMR1); break;
+    STORAGE(USBLMPR2); break;
+
+    default:
+        printf("--- Write %08x to 1f8%05x: peripheral register not supported\n",
+            data, offset);
+        if (TRACE) {
+            fprintf(qemu_logfile,
+            "--- Write %08x to 1f8%05x: peripheral register not supported\n",
+                data, offset);
+        }
+        exit(1);
+readonly:
+        printf("--- Write %08x to %s: readonly register\n",
+            data, *namep);
+        if (TRACE) {
+            fprintf(qemu_logfile, "--- Write %08x to %s: readonly register\n",
+                data, *namep);
+        }
+        *namep = 0;
+        return;
+    }
+    *bufp = data;
+}
+
+static uint64_t pic32_io_read(void *opaque, hwaddr addr, unsigned bytes)
+{
+    pic32_t *s = opaque;
+    uint32_t offset = addr & 0xfffff;
+    const char *name = "???";
+    uint32_t data = 0;
+
+    data = io_read32(s, offset & ~3, &name);
+    switch (bytes) {
+    case 1:
+        offset &= 3;
+        if (offset != 0) {
+            /* Unaligned read. */
+            data >>= offset * 8;
+        }
+        data = (uint8_t) data;
+        if (TRACE) {
+            fprintf(qemu_logfile, "--- I/O Read  %02x from %s\n", data, name);
+        }
+        break;
+    case 2:
+        if (offset & 2) {
+            /* Unaligned read. */
+            data >>= 16;
+        }
+        data = (uint16_t) data;
+        if (TRACE) {
+            fprintf(qemu_logfile, "--- I/O Read  %04x from %s\n", data, name);
+        }
+        break;
+    default:
+        if (TRACE) {
+            fprintf(qemu_logfile, "--- I/O Read  %08x from %s\n", data, name);
+        }
+        break;
+    }
+    return data;
+}
+
+static void pic32_io_write(void *opaque, hwaddr addr, uint64_t data,
+    unsigned bytes)
+{
+    pic32_t *s = opaque;
+    uint32_t offset = addr & 0xfffff;
+    const char *name = "???";
+
+    /* Fetch data and align to word format. */
+    switch (bytes) {
+    case 1:
+        data = (uint8_t) data;
+        data <<= (offset & 3) * 8;
+        break;
+    case 2:
+        data = (uint16_t) data;
+        data <<= (offset & 2) * 8;
+        break;
+    }
+    io_write32(s, offset & ~3, data, &name);
+
+    if (TRACE && name != 0) {
+        fprintf(qemu_logfile, "--- I/O Write %08x to %s\n",
+            (uint32_t) data, name);
+    }
+}
+
+/*
+ * This function is called when the processor is stopped
+ * on WAIT instruction, waiting for external interrupt.
+ */
+static void pic32_exec_exit(CPUState *cs)
+{
+    MIPSCPU *cpu = MIPS_CPU(cs);
+    CPUMIPSState *env = &cpu->env;
+
+    if (cs->halted && !(env->CP0_Status & (1 << CP0St_IE))) {
+        /* WAIT instruction with interrupts disabled - halt the simulation. */
+        qemu_system_shutdown_request();
+    }
+}
+
+static const MemoryRegionOps pic32_io_ops = {
+    .read       = pic32_io_read,
+    .write      = pic32_io_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void main_cpu_reset(void *opaque)
+{
+    MIPSCPU *cpu = opaque;
+    CPUMIPSState *env = &cpu->env;
+    int i;
+
+    cpu_reset(CPU(cpu));
+
+    /* Adjust the initial configuration for microAptivP core. */
+    env->CP0_IntCtl = 0x00030000;
+    env->CP0_Debug = (1 << CP0DB_CNT) | (5 << CP0DB_VER);
+    env->CP0_Performance0 = 0x80000000;
+    for (i = 0; i < 7; i++) {
+        env->CP0_WatchHi[i] = (i < 3) ? 0x80000000 : 0;
+    }
+}
+
+static void store_byte(unsigned address, unsigned char byte)
+{
+    if (address >= PROGRAM_FLASH_START &&
+        address < PROGRAM_FLASH_START + PROGRAM_FLASH_SIZE) {
+        /*printf("Store %02x to program memory %08x\n", byte, address);*/
+        prog_ptr[address & 0xfffff] = byte;
+        return;
+    }
+
+    if (address >= BOOT_FLASH_START &&
+        address < BOOT_FLASH_START + BOOT_FLASH_SIZE) {
+        /*printf("Store %02x to boot memory %08x\n", byte, address);*/
+        boot_ptr[address & 0xffff] = byte;
+        return;
+    }
+
+    printf("Bad hex file: "
+        "incorrect address %08X, must be %08X-%08X or %08X-%08X\n",
+        address, PROGRAM_FLASH_START,
+        PROGRAM_FLASH_START + PROGRAM_FLASH_SIZE - 1,
+        BOOT_FLASH_START, BOOT_FLASH_START + BOOT_FLASH_SIZE - 1);
+    exit(1);
+}
+
+/*
+ * Ignore ^C and ^\ signals and pass these characters to the target.
+ */
+static void pic32_pass_signal_chars(void)
+{
+    struct termios tty;
+
+    tcgetattr(0, &tty);
+    tty.c_lflag &= ~ISIG;
+    tcsetattr(0, TCSANOW, &tty);
+}
+
+static void pic32_init(MachineState *machine, int board_type)
+{
+    const char *cpu_model = machine->cpu_model;
+    unsigned ram_size = DATA_MEM_SIZE;
+    MemoryRegion *system_memory = get_system_memory();
+    MemoryRegion *ram_main = g_new(MemoryRegion, 1);
+    MemoryRegion *prog_mem = g_new(MemoryRegion, 1);
+    MemoryRegion *boot_mem = g_new(MemoryRegion, 1);
+    MemoryRegion *io_mem = g_new(MemoryRegion, 1);
+    MIPSCPU *cpu;
+    CPUMIPSState *env;
+
+    DeviceState *dev = qdev_create(NULL, TYPE_MIPS_PIC32);
+    pic32_t *s = OBJECT_CHECK(pic32_t, dev, TYPE_MIPS_PIC32);
+    s->board_type = board_type;
+    s->stop_on_reset = 1;               /* halt simulation on soft reset */
+    s->iomem = g_malloc0(IO_MEM_SIZE);  /* backing storage for I/O area */
+
+    qdev_init_nofail(dev);
+
+    /* Init CPU. */
+    if (!cpu_model) {
+        cpu_model = "microAptivP";
+    }
+    printf("Board: %s\n", board_name[board_type]);
+    if (qemu_logfile) {
+        fprintf(qemu_logfile, "Board: %s\n", board_name[board_type]);
+    }
+    printf("Processor: %s\n", cpu_model);
+    if (qemu_logfile) {
+        fprintf(qemu_logfile, "Processor: %s\n", cpu_model);
+    }
+    cpu = cpu_mips_init(cpu_model);
+    if (!cpu) {
+        fprintf(stderr, "Unable to find CPU definition\n");
+        exit(1);
+    }
+    s->cpu = cpu;
+    env = &cpu->env;
+
+    /* Register RAM */
+    printf("RAM size: %u kbytes\n", ram_size / 1024);
+    if (qemu_logfile) {
+        fprintf(qemu_logfile, "RAM size: %u kbytes\n", ram_size / 1024);
+    }
+    memory_region_init_ram(ram_main, NULL, "kernel.ram",
+        ram_size, &error_abort);
+    vmstate_register_ram_global(ram_main);
+    memory_region_add_subregion(system_memory, DATA_MEM_START, ram_main);
+
+    /* Special function registers. */
+    memory_region_init_io(io_mem, NULL, &pic32_io_ops, s,
+                          "io", IO_MEM_SIZE);
+    memory_region_add_subregion(system_memory, IO_MEM_START, io_mem);
+
+    /*
+     * Map the flash memory.
+     */
+    memory_region_init_ram(boot_mem, NULL, "boot.flash",
+        BOOT_FLASH_SIZE, &error_abort);
+    memory_region_init_ram(prog_mem, NULL, "prog.flash",
+        PROGRAM_FLASH_SIZE, &error_abort);
+
+    /* Load a Flash memory image. */
+    if (!machine->kernel_filename) {
+        error_report("No -kernel argument was specified.");
+        exit(1);
+    }
+    prog_ptr = memory_region_get_ram_ptr(prog_mem);
+    boot_ptr = memory_region_get_ram_ptr(boot_mem);
+    if (bios_name) {
+        pic32_load_hex_file(bios_name, store_byte);
+    }
+    pic32_load_hex_file(machine->kernel_filename, store_byte);
+
+    memory_region_set_readonly(boot_mem, true);
+    memory_region_set_readonly(prog_mem, true);
+    memory_region_add_subregion(system_memory, BOOT_FLASH_START, boot_mem);
+    memory_region_add_subregion(system_memory, PROGRAM_FLASH_START, prog_mem);
+
+    /* Init internal devices */
+    s->irq_raise = irq_raise;
+    s->irq_clear = irq_clear;
+    qemu_register_reset(main_cpu_reset, cpu);
+
+    /* Setup interrupt controller in EIC mode. */
+    env->CP0_Config3 |= 1 << CP0C3_VEIC;
+    cpu_mips_irq_init_cpu(env);
+    env->eic_timer_irq = pic32_timer_irq;
+    env->eic_soft_irq = pic32_soft_irq;
+    env->eic_context = s;
+
+    /* CPU runs at 200MHz.
+     * Count register increases at half this rate. */
+    cpu_mips_clock_init(env, 100*1000*1000);
+
+    /* Setup callback for CPU halt. */
+    MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(cpu);
+    CPUClass *cc = CPU_CLASS(mcc);
+    cc->cpu_exec_exit = pic32_exec_exit;
+
+    /*
+     * Initialize board-specific parameters.
+     */
+    int cs0_port, cs0_pin, cs1_port, cs1_pin;
+    switch (board_type) {
+    default:
+    case BOARD_WIFIRE:                      /* console on UART4 */
+        BOOTMEM(DEVCFG0) = 0xfffffff7;
+        BOOTMEM(DEVCFG1) = 0x7f743cb9;
+        BOOTMEM(DEVCFG2) = 0xfff9b11a;
+        BOOTMEM(DEVCFG3) = 0xbeffffff;
+        VALUE(DEVID)     = 0x4510e053;      /* MZ2048ECG100 rev A4 */
+        VALUE(OSCCON)    = 0x00001120;      /* external oscillator 24MHz */
+        s->sdcard_spi_port = 2;             /* SD card at SPI3, */
+        cs0_port = 2;  cs0_pin = 3;         /* select0 at C3, */
+        cs1_port = -1; cs1_pin = -1;        /* select1 not available */
+        break;
+    case BOARD_MEBII:                       /* console on UART1 */
+        BOOTMEM(DEVCFG0) = 0x7fffffdb;
+        BOOTMEM(DEVCFG1) = 0x0000fc81;
+        BOOTMEM(DEVCFG2) = 0x3ff8b11a;
+        BOOTMEM(DEVCFG3) = 0x86ffffff;
+        VALUE(DEVID)     = 0x45127053;      /* MZ2048ECH144 rev A4 */
+        VALUE(OSCCON)    = 0x00001120;      /* external oscillator 24MHz */
+        s->sdcard_spi_port = 1;             /* SD card at SPI2, */
+        cs0_port = 1;  cs0_pin = 14;        /* select0 at B14, */
+        cs1_port = -1; cs1_pin = -1;        /* select1 not available */
+        break;
+    case BOARD_EXPLORER16:                  /* console on UART1 */
+        BOOTMEM(DEVCFG0) = 0x7fffffdb;
+        BOOTMEM(DEVCFG1) = 0x0000fc81;
+        BOOTMEM(DEVCFG2) = 0x3ff8b11a;
+        BOOTMEM(DEVCFG3) = 0x86ffffff;
+        VALUE(DEVID)     = 0x35113053;      /* MZ2048ECH100 rev A3 */
+        VALUE(OSCCON)    = 0x00001120;      /* external oscillator 24MHz */
+        s->sdcard_spi_port = 0;             /* SD card at SPI1, */
+        cs0_port = 1;  cs0_pin = 1;         /* select0 at B1, */
+        cs1_port = 1;  cs1_pin = 2;         /* select1 at B2 */
+        break;
+    }
+
+    /* UARTs */
+    pic32_uart_init(s, 0, PIC32_IRQ_U1E, U1STA, U1MODE);
+    pic32_uart_init(s, 1, PIC32_IRQ_U2E, U2STA, U2MODE);
+    pic32_uart_init(s, 2, PIC32_IRQ_U3E, U3STA, U3MODE);
+    pic32_uart_init(s, 3, PIC32_IRQ_U4E, U4STA, U4MODE);
+    pic32_uart_init(s, 4, PIC32_IRQ_U5E, U5STA, U5MODE);
+    pic32_uart_init(s, 5, PIC32_IRQ_U6E, U6STA, U6MODE);
+
+    /* SPIs */
+    pic32_spi_init(s, 0, PIC32_IRQ_SPI1E, SPI1CON, SPI1STAT);
+    pic32_spi_init(s, 1, PIC32_IRQ_SPI2E, SPI2CON, SPI2STAT);
+    pic32_spi_init(s, 2, PIC32_IRQ_SPI3E, SPI3CON, SPI3STAT);
+    pic32_spi_init(s, 3, PIC32_IRQ_SPI4E, SPI4CON, SPI4STAT);
+    pic32_spi_init(s, 4, PIC32_IRQ_SPI5E, SPI5CON, SPI5STAT);
+    pic32_spi_init(s, 5, PIC32_IRQ_SPI6E, SPI6CON, SPI6STAT);
+
+    /*
+     * Load SD card images.
+     * Use options:
+     *      -sd filename
+     * or   -hda filename
+     * and  -hdb filename
+     */
+    const char *sd0_file = 0, *sd1_file = 0;
+    DriveInfo *dinfo = drive_get(IF_IDE, 0, 0);
+    if (dinfo) {
+        sd0_file = qemu_opt_get(dinfo->opts, "file");
+        dinfo->is_default = 1;
+
+        dinfo = drive_get(IF_IDE, 0, 1);
+        if (dinfo) {
+            sd1_file = qemu_opt_get(dinfo->opts, "file");
+            dinfo->is_default = 1;
+        }
+    }
+    if (!sd0_file) {
+        dinfo = drive_get(IF_SD, 0, 0);
+        if (dinfo) {
+            sd0_file = qemu_opt_get(dinfo->opts, "file");
+            dinfo->is_default = 1;
+        }
+    }
+    pic32_sdcard_init(s, 0, "sd0", sd0_file, cs0_port, cs0_pin);
+    pic32_sdcard_init(s, 1, "sd1", sd1_file, cs1_port, cs1_pin);
+
+    /* Ethernet. */
+    if (nd_table[0].used) {
+        pic32_eth_init(s, &nd_table[0]);
+    }
+    io_reset(s);
+    pic32_sdcard_reset(s);
+    pic32_pass_signal_chars();
+}
+
+static void pic32_init_wifire(MachineState *machine)
+{
+    pic32_init(machine, BOARD_WIFIRE);
+}
+
+static void pic32_init_meb2(MachineState *machine)
+{
+    pic32_init(machine, BOARD_MEBII);
+}
+
+static void pic32_init_explorer16(MachineState *machine)
+{
+    pic32_init(machine, BOARD_EXPLORER16);
+}
+
+static int pic32_sysbus_device_init(SysBusDevice *sysbusdev)
+{
+    return 0;
+}
+
+static void pic32_class_init(ObjectClass *klass, void *data)
+{
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = pic32_sysbus_device_init;
+}
+
+static const TypeInfo pic32_device = {
+    .name          = TYPE_MIPS_PIC32,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(pic32_t),
+    .class_init    = pic32_class_init,
+};
+
+static void pic32_register_types(void)
+{
+    type_register_static(&pic32_device);
+}
+
+static QEMUMachine pic32_board[3] = {
+    {
+        .name       = "pic32mz-wifire",
+        .desc       = "PIC32MZ microcontroller on chipKIT WiFire board",
+        .init       = pic32_init_wifire,
+        .max_cpus   = 1,
+    },
+    {
+        .name       = "pic32mz-meb2",
+        .desc       = "PIC32MZ microcontroller on Microchip MEB-II board",
+        .init       = pic32_init_meb2,
+        .max_cpus   = 1,
+    },
+    {
+        .name       = "pic32mz-explorer16",
+        .desc       = "PIC32MZ microcontroller on Microchip Explorer-16 board",
+        .init       = pic32_init_explorer16,
+        .max_cpus   = 1,
+    },
+};
+
+static void pic32_machine_init(void)
+{
+    qemu_register_machine(&pic32_board[0]);
+    qemu_register_machine(&pic32_board[1]);
+    qemu_register_machine(&pic32_board[2]);
+}
+
+type_init(pic32_register_types)
+machine_init(pic32_machine_init);
+
+#endif /* !TARGET_MIPS64 && !TARGET_WORDS_BIGENDIAN */
diff --git a/hw/mips/pic32_ethernet.c b/hw/mips/pic32_ethernet.c
new file mode 100644
index 0000000..383effd
--- /dev/null
+++ b/hw/mips/pic32_ethernet.c
@@ -0,0 +1,557 @@ 
+/*
+ * Ethernet port.
+ *
+ * Copyright (C) 2014-2015 Serge Vakulenko
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that the copyright notice and this
+ * permission notice and warranty disclaimer appear in supporting
+ * documentation, and that the name of the author not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ *
+ * The author disclaim all warranties with regard to this
+ * software, including all implied warranties of merchantability
+ * and fitness.  In no event shall the author be liable for any
+ * special, indirect or consequential damages or any damages
+ * whatsoever resulting from loss of use, data or profits, whether
+ * in an action of contract, negligence or other tortious action,
+ * arising out of or in connection with the use or performance of
+ * this software.
+ */
+#include "hw/hw.h"
+#include "exec/address-spaces.h"
+#include "sysemu/dma.h"
+#include "pic32_peripherals.h"
+
+#include "pic32mz.h"
+
+/*#define DPRINT printf */
+#ifndef DPRINT
+#define DPRINT(...) /*empty*/
+#endif
+
+/*
+ * TODO: add option to enable tracing.
+ */
+#define TRACE   0
+
+#define NAME_PIC32_ETH "pic32-eth"
+
+#define MIN_RX_SIZE 60
+
+/*
+ * PIC32 Ethernet device.
+ */
+struct _eth_t {
+    SysBusDevice parent_obj;
+
+    pic32_t     *pic32;
+    NICState    *eth_nic;       /* virtual network interface */
+    NICConf     eth_conf;       /* network configuration */
+
+    uint16_t    phy_reg[32];    /* PHY registers */
+
+};
+
+/*
+ * DMA buffer descriptor.
+ */
+typedef struct {
+    uint32_t hdr;               /* Flags */
+    uint32_t paddr;             /* Phys address of data buffer */
+    uint32_t ctl;               /* TX options / RX filter status */
+    uint32_t status;            /* Status */
+} eth_desc_t;
+
+/* Start of packet */
+#define DESC_SOP(d)             ((d)->hdr & 0x80000000)
+#define DESC_SET_SOP(d)         ((d)->hdr |= 0x80000000)
+#define DESC_CLEAR_SOP(d)       ((d)->hdr &= ~0x80000000)
+
+/* End of packet */
+#define DESC_EOP(d)             ((d)->hdr & 0x40000000)
+#define DESC_SET_EOP(d)         ((d)->hdr |= 0x40000000)
+#define DESC_CLEAR_EOP(d)       ((d)->hdr &= ~0x40000000)
+
+/* Number of data bytes */
+#define DESC_BYTECNT(d)         ((d)->hdr >> 16 & 0x7ff)
+#define DESC_SET_BYTECNT(d, n)  ((d)->hdr = ((d)->hdr & ~0x7ff0000) | (n) << 16)
+
+/* Next descriptor pointer valid */
+#define DESC_NPV(d)             ((d)->hdr & 0x00000100)
+#define DESC_SET_NPV(d)         ((d)->hdr |= 0x00000100)
+#define DESC_CLEAR_NPV(d)       ((d)->hdr &= ~0x00000100)
+
+/* Eth controller owns this desc */
+#define DESC_EOWN(d)            ((d)->hdr & 0x00000080)
+#define DESC_SET_EOWN(d)        ((d)->hdr |= 0x00000080)
+#define DESC_CLEAR_EOWN(d)      ((d)->hdr &= ~0x00000080)
+
+/* Size of received packet */
+#define DESC_FRAMESZ(d)         ((d)->status & 0xffff)
+#define DESC_SET_FRAMESZ(d, n)  ((d)->status = ((d)->status & ~0xffff) | (n))
+
+/* Receive filter status */
+#define DESC_RXF(d)             ((d)->ctl >> 24)
+#define DESC_SET_RXF(d, n)      ((d)->ctl = ((d)->ctl & 0xffffff) | (n) << 24)
+
+/*-------------------------------------------------------------
+ * PHY declarations for SMSC LAN8720A/8740A chip.
+ */
+#define PHY_CONTROL             0       /* Basic Control Register */
+#define PHY_STATUS              1       /* Basic Status Register */
+#define PHY_ID1                 2       /* PHY identifier 1 */
+#define PHY_ID2                 3       /* PHY identifier 2 */
+#define PHY_MODE                18      /* Special Modes */
+#define PHY_SPECIAL             31      /* Special Control/Status Register */
+
+#define PHY_CONTROL_RESET       0x8000  /* Soft reset, bit self cleared */
+
+#define PHY_STATUS_CAP_100_FDX  0x4000  /* Can do 100Base-TX full duplex */
+#define PHY_STATUS_CAP_100_HDX  0x2000  /* Can do 100Base-TX half duplex */
+#define PHY_STATUS_CAP_10_FDX   0x1000  /* Can do 10Base-TX full duplex */
+#define PHY_STATUS_CAP_10_HDX   0x0800  /* Can do 10Base-TX half duplex */
+#define PHY_STATUS_ANEG_ACK     0x0020  /* Auto-negotiation acknowledge */
+#define PHY_STATUS_CAP_ANEG     0x0008  /* Auto-negotiation available */
+#define PHY_STATUS_LINK         0x0004  /* Link valid */
+
+#define PHY_MODE_PHYAD          0x000f  /* PHY address mask */
+
+#define PHY_SPECIAL_AUTODONE    0x1000  /* Auto-negotiation is done */
+#define PHY_SPECIAL_FDX         0x0010  /* Full duplex */
+#define PHY_SPECIAL_100         0x0008  /* Speed 100 Mbps */
+
+/*
+ * Reset the PHY chip.
+ */
+static void phy_reset(eth_t *e)
+{
+    DPRINT("---     PHY reset\n");
+    e->phy_reg[PHY_ID1]     = 0x0007;               /* Vendor: SMSC */
+    e->phy_reg[PHY_ID2]     = 0xc111;               /* Device: LAN8740A */
+    e->phy_reg[PHY_CONTROL] = 0x1000;
+    e->phy_reg[PHY_MODE]    = 0x4000;               /* RMII interface */
+    e->phy_reg[PHY_STATUS]  = PHY_STATUS_ANEG_ACK |
+                              PHY_STATUS_CAP_ANEG |
+                              PHY_STATUS_LINK |
+                              PHY_STATUS_CAP_100_FDX |
+                              PHY_STATUS_CAP_100_HDX |
+                              PHY_STATUS_CAP_10_FDX |
+                              PHY_STATUS_CAP_10_HDX;
+    e->phy_reg[PHY_SPECIAL] = PHY_SPECIAL_AUTODONE |
+                              PHY_SPECIAL_FDX |
+                              PHY_SPECIAL_100;
+}
+
+/*
+ * Reset the Ethernet controller.
+ */
+static void eth_reset(eth_t *e)
+{
+    uint8_t *macaddr = e->eth_conf.macaddr.a;
+    pic32_t *s = e->pic32;
+
+    DPRINT("--- %s()\n", __func__);
+    if (TRACE) {
+        fprintf(qemu_logfile, "--- Ethernet reset\n");
+    }
+    s->irq_clear(s, PIC32_IRQ_ETH);
+    VALUE(ETHSTAT) = 0;
+    VALUE(EMAC1SA2) = macaddr[0] | (macaddr[1] << 8);
+    VALUE(EMAC1SA1) = macaddr[2] | (macaddr[3] << 8);
+    VALUE(EMAC1SA0) = macaddr[4] | (macaddr[5] << 8);
+}
+
+/*
+ * Write to ETHCON1 register.
+ */
+void pic32_eth_control(pic32_t *s)
+{
+    eth_t *e = s->eth;
+
+    if (!(VALUE(ETHCON1) & PIC32_ETHCON1_ON)) {
+        /* Ethernet controller is disabled. */
+        DPRINT("--- %s() ETH disabled\n", __func__);
+        eth_reset(e);
+        return;
+    }
+
+    if (VALUE(ETHCON1) & PIC32_ETHCON1_TXRTS) {
+        /* Transmit request. */
+        eth_desc_t d = { 0 };
+        unsigned paddr = VALUE(ETHTXST);
+        unsigned nbytes, i;
+        unsigned char buf[2048];
+
+        d.hdr   = ldl_le_phys(&address_space_memory, paddr);
+        d.paddr = ldl_le_phys(&address_space_memory, paddr + 4);
+
+        nbytes = DESC_BYTECNT(&d);
+        DPRINT("--- %s() trasmit request %u bytes\n", __func__, nbytes);
+        DPRINT("--- TX desc [%08x] = %08x %08x\n", paddr, d.hdr, d.paddr);
+        if (TRACE) {
+            fprintf(qemu_logfile, "--- Ethernet transmit request, %u bytes\n",
+                nbytes);
+        }
+        if (nbytes > 0 && nbytes <= sizeof(buf)) {
+            for (i = 0; i < nbytes; i += 4)
+                *(uint32_t *) (buf + i) = ldl_le_phys(&address_space_memory,
+                                                      d.paddr + i);
+
+            DPRINT("--- %u bytes of data: %02x", nbytes, buf[0]);
+            for (i = 1; i < nbytes; i++) {
+                DPRINT("-%02x", buf[i]);
+            }
+            DPRINT("\n");
+
+            qemu_send_packet(qemu_get_queue(e->eth_nic), buf, nbytes);
+        }
+
+        /* Activate TXDONE interrupt. */
+        VALUE(ETHCON1) &= ~PIC32_ETHCON1_TXRTS;
+        VALUE(ETHIRQ) |= PIC32_ETHIRQ_TXDONE;
+        s->irq_raise(s, PIC32_IRQ_ETH);
+    }
+}
+
+/*
+ * Write to EMAC1MCMD register.
+ */
+void pic32_mii_command(pic32_t *s)
+{
+    eth_t *e = s->eth;
+    unsigned cmd = VALUE(EMAC1MCMD);
+    unsigned addr = VALUE(EMAC1MADR);
+    unsigned data;
+
+    if (cmd & (PIC32_EMAC1MCMD_READ | PIC32_EMAC1MCMD_SCAN)) {
+        data = e->phy_reg[addr & 0x1f];
+        /*DPRINT("--- %s() cmd = %04x, addr = %04x\n", __func__, cmd, addr);*/
+        DPRINT("--- %s() read register [%u] = %04x\n", __func__, addr & 0x1f,
+            data);
+        if (TRACE) {
+            fprintf(qemu_logfile,
+                "--- Ethernet MII read register [%u] = %04x\n",
+                addr & 0x1f, data);
+        }
+        VALUE(EMAC1MRDD) = data;
+    }
+}
+
+/*
+ * Write to EMAC1MWTD register.
+ */
+void pic32_mii_write(pic32_t *s)
+{
+    eth_t *e = s->eth;
+    unsigned addr = VALUE(EMAC1MADR);
+    unsigned data = VALUE(EMAC1MWTD);
+
+    DPRINT("--- %s() write register [%u] = %04x\n", __func__, addr & 0x1f,
+        data);
+    if (TRACE) {
+        fprintf(qemu_logfile, "--- Ethernet MII write register [%u] = %04x\n",
+            addr & 0x1f, data);
+    }
+    switch (addr & 0x1f) {
+    case PHY_CONTROL:                   /* Basic Control Register */
+        e->phy_reg[PHY_CONTROL] = data;
+        if (data & PHY_CONTROL_RESET) {
+            phy_reset(e);
+        }
+        break;
+    }
+}
+
+/*
+ * Return true when no receive buffers available.
+ */
+static int eth_buffer_full(pic32_t *s)
+{
+    eth_desc_t d = { 0 };
+
+    d.hdr = ldl_le_phys(&address_space_memory, VALUE(ETHRXST));
+    return !DESC_EOWN(&d);
+}
+
+/*
+ * Return true when we are ready to receive a packet.
+ */
+static int nic_can_receive(NetClientState *nc)
+{
+    eth_t *e = qemu_get_nic_opaque(nc);
+    pic32_t *s = e->pic32;
+
+    /*DPRINT("--- %s()\n", __func__);*/
+    if (!(VALUE(ETHCON1) & PIC32_ETHCON1_ON)) {
+        /* While interface is down,
+         * we can receive anything (and discard). */
+        return 1;
+    }
+
+    /* Check whether we have at least one receive buffer available. */
+    return !eth_buffer_full(s);
+}
+
+/*
+ * Receive a packet.
+ */
+static ssize_t nic_receive(NetClientState *nc, const uint8_t *buf, size_t size)
+{
+    eth_t *e = qemu_get_nic_opaque(nc);
+    pic32_t *s = e->pic32;
+    unsigned rxfc, rxf, rxst, rxst0, rxbufsz, nbytes, len;
+    int start_of_packet;
+    uint8_t buf1[60];
+    eth_desc_t *d, desc0, desc1;
+
+    DPRINT("--- %s: %d bytes\n", __func__, (int) size);
+    if (TRACE) {
+        fprintf(qemu_logfile, "--- Ethernet receive, %u bytes\n",
+            (unsigned)size);
+    }
+    if (!(VALUE(ETHCON1) & PIC32_ETHCON1_ON)) {
+        /* Ethernet controller is down. */
+        return -1;
+    }
+
+    if (eth_buffer_full(s)) {
+        return -1;
+    }
+
+    /* Cast acceptance filter. */
+    rxfc = VALUE(ETHRXFC);
+    if (buf[0] == 0xff && buf[1] == 0xff && buf[2] == 0xff &&
+        buf[3] == 0xff && buf[4] == 0xff && buf[5] == 0xff) {
+        /* Broadcast address. */
+        if (!(rxfc & PIC32_ETHRXFC_BCEN)) {
+            return size;
+        }
+        rxf = 0x40;
+    } else if (buf[0] & 0x01) {
+        /* Multicast. */
+        if (!(rxfc & PIC32_ETHRXFC_MCEN)) {
+            return size;
+        }
+        rxf = 0x80;
+    } else if (VALUE(EMAC1SA2) == (buf[0] | (buf[1] << 8)) ||
+               VALUE(EMAC1SA2) == (buf[2] | (buf[3] << 8)) ||
+               VALUE(EMAC1SA2) == (buf[4] | (buf[5] << 8))) {
+        /* Unicast for our MAC address. */
+        if (!(rxfc & PIC32_ETHRXFC_UCEN)) {
+            return size;
+        }
+        rxf = 0x20;
+    } else {
+        /* Not-Me Unicast. */
+        if (!(rxfc & PIC32_ETHRXFC_NOTMEEN)) {
+            return size;
+        }
+        rxf = 0x00;
+    }
+
+    /* If packet too small, then expand it */
+    nbytes = size;
+    if (nbytes < MIN_RX_SIZE) {
+        memcpy(buf1, buf, nbytes);
+        memset(buf1 + nbytes, 0, MIN_RX_SIZE - nbytes);
+        buf = buf1;
+        nbytes = MIN_RX_SIZE;
+    }
+
+    /* Copy data to descriptor chain. */
+    rxst0 = VALUE(ETHRXST);
+    rxbufsz = VALUE(ETHCON2) & 0x7f0;
+    start_of_packet = 1;
+    d = &desc0;
+    rxst = rxst0;
+    for (;;) {
+        /* Get descriptor. */
+        dma_memory_read(&address_space_memory, rxst, d, 16);
+        if (!DESC_EOWN(d) || (!start_of_packet && rxst == rxst0)) {
+            DPRINT("--- No more descriptors available\n");
+            VALUE(ETHIRQ) |= PIC32_ETHIRQ_RXBUFNA;
+            break;
+        }
+
+        /* Copy data to buffer. */
+        len = nbytes;
+        if (len > rxbufsz) {
+            len = rxbufsz;
+        }
+        DPRINT("--- Copy %d bytes to %08x\n", len, d->paddr);
+        dma_memory_write(&address_space_memory, d->paddr, buf, len);
+        buf += len;
+
+        /* Update the descriptor. */
+        DESC_CLEAR_EOWN(d);
+        DESC_SET_BYTECNT(d, len);
+        if (start_of_packet) {
+            DESC_SET_SOP(d);
+            DESC_SET_FRAMESZ(d, nbytes);
+            DESC_SET_RXF(d, rxf);
+            start_of_packet = 0;
+        } else {
+            DESC_CLEAR_SOP(d);
+        }
+        if (nbytes == len) {
+            DESC_SET_EOP(d);
+        } else {
+            DESC_CLEAR_EOP(d);
+        }
+
+        /* Write the descriptor back memory (all but the first). */
+        if (d == &desc1) {
+            DPRINT("--- RX desc [%08x] = %08x ... ... %08x\n", rxst,
+                desc1.hdr, desc1.status);
+            dma_memory_write(&address_space_memory, rxst, &desc1, 16);
+        }
+
+        /* Switch to next descriptor. */
+        rxst += 16;
+        if (DESC_NPV(d)) {
+            rxst = ldl_le_phys(&address_space_memory, rxst);
+        }
+        VALUE(ETHRXST) = rxst;
+        d = &desc1;
+
+        nbytes -= len;
+        if (nbytes == 0) {
+            /* Update the first descriptor. */
+            DPRINT("--- RX desc [%08x] = %08x ... ... %08x\n",
+                rxst0, desc0.hdr, desc0.status);
+            dma_memory_write(&address_space_memory, rxst0, &desc0, 16);
+
+            /* Packet successfully received. */
+            VALUE(ETHIRQ) |= PIC32_ETHIRQ_RXDONE;
+            break;
+        }
+    }
+
+    /* Activate interrupt. */
+    s->irq_raise(s, PIC32_IRQ_ETH);
+    return size;
+}
+
+/*
+ * Deallocate the QEMU network interface.
+ */
+static void nic_cleanup(NetClientState *nc)
+{
+    eth_t *e = qemu_get_nic_opaque(nc);
+
+    /*DPRINT("--- %s()\n", __func__);*/
+    e->eth_nic = 0;
+}
+
+/*
+ * Initialize Ethernet device.
+ */
+void pic32_eth_init(pic32_t *s, NICInfo *nd)
+{
+    DPRINT("--- %s()\n", __func__);
+
+    /* Create Ethernet device. */
+    s->eth_dev = qdev_create(NULL, NAME_PIC32_ETH);
+    qdev_set_nic_properties(s->eth_dev, nd);
+    qdev_init_nofail(s->eth_dev);
+
+    /* Setup back pointer from Ethernet device to pic32 object. */
+    s->eth = OBJECT_CHECK(eth_t, s->eth_dev, NAME_PIC32_ETH);
+    s->eth->pic32 = s;
+}
+
+/*
+ * Initialize pic32-eth object.
+ */
+static int eth_object_init(SysBusDevice *sbd)
+{
+    /* Table of methods for QEMU network interface. */
+    static NetClientInfo nic_info = {
+        .type           = NET_CLIENT_OPTIONS_KIND_NIC,
+        .size           = sizeof(NICState),
+        .can_receive    = nic_can_receive,
+        .receive        = nic_receive,
+        .cleanup        = nic_cleanup,
+    };
+    DeviceState *dev = DEVICE(sbd);
+    eth_t *e = OBJECT_CHECK(eth_t, dev, NAME_PIC32_ETH);
+
+    /*DPRINT("--- %s()\n", __func__);*/
+
+    /* Initialize MAC address. */
+    qemu_macaddr_default_if_unset(&e->eth_conf.macaddr);
+
+    /* Create a QEMU network interface. */
+    e->eth_nic = qemu_new_nic(&nic_info, &e->eth_conf,
+        object_get_typename(OBJECT(dev)), dev->id, e);
+
+    qemu_format_nic_info_str(qemu_get_queue(e->eth_nic),
+        e->eth_conf.macaddr.a);
+
+    return 0;
+}
+
+/*
+ * Reset pic32-eth object.
+ */
+static void eth_object_reset(DeviceState *dev)
+{
+    eth_t *e = OBJECT_CHECK(eth_t, dev, NAME_PIC32_ETH);
+
+    /*DPRINT("--- %s()\n", __func__);*/
+    eth_reset(e);
+    phy_reset(e);
+}
+
+/*
+ * Descriptor of eth_t data structure.
+ */
+static const VMStateDescription vmstate_info = {
+    .name               = NAME_PIC32_ETH,
+    .version_id         = 0,
+    .minimum_version_id = 0,
+    .fields             = (VMStateField[]) {
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+/*
+ * Build pic32-eth object.
+ */
+static void eth_object_constructor(ObjectClass *klass, void *data)
+{
+    static Property eth_properties[] = {
+        DEFINE_NIC_PROPERTIES(eth_t, eth_conf),
+        DEFINE_PROP_END_OF_LIST(),
+    };
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+    k->init = eth_object_init;
+    set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
+    dc->desc = "PIC32 Ethernet device";
+    dc->reset = eth_object_reset;
+    dc->vmsd = &vmstate_info;
+    dc->props = eth_properties;
+}
+
+/*
+ * Instantiate pic32-eth class.
+ */
+static void eth_register_types(void)
+{
+    static const TypeInfo eth_class_info = {
+        .name          = NAME_PIC32_ETH,
+        .parent        = TYPE_SYS_BUS_DEVICE,
+        .instance_size = sizeof(eth_t),
+        .class_init    = eth_object_constructor,
+    };
+
+    type_register_static(&eth_class_info);
+}
+
+type_init(eth_register_types)
diff --git a/hw/mips/pic32_gpio.c b/hw/mips/pic32_gpio.c
new file mode 100644
index 0000000..670d2b6
--- /dev/null
+++ b/hw/mips/pic32_gpio.c
@@ -0,0 +1,39 @@ 
+/*
+ * GPIO ports.
+ *
+ * Copyright (C) 2015 Serge Vakulenko
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that the copyright notice and this
+ * permission notice and warranty disclaimer appear in supporting
+ * documentation, and that the name of the author not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ *
+ * The author disclaim all warranties with regard to this
+ * software, including all implied warranties of merchantability
+ * and fitness.  In no event shall the author be liable for any
+ * special, indirect or consequential damages or any damages
+ * whatsoever resulting from loss of use, data or profits, whether
+ * in an action of contract, negligence or other tortious action,
+ * arising out of or in connection with the use or performance of
+ * this software.
+ */
+#include "hw/hw.h"
+#include "pic32_peripherals.h"
+
+#include "pic32mz.h"
+
+void pic32_gpio_write(pic32_t *s, int gpio_port, unsigned lat_value)
+{
+    /* Control SD card 0 */
+    if (gpio_port == s->sdcard[0].gpio_port && s->sdcard[0].gpio_cs) {
+        pic32_sdcard_select(s, 0, !(lat_value & s->sdcard[0].gpio_cs));
+    }
+    /* Control SD card 1 */
+    if (gpio_port == s->sdcard[1].gpio_port && s->sdcard[0].gpio_cs) {
+        pic32_sdcard_select(s, 1, !(lat_value & s->sdcard[1].gpio_cs));
+    }
+}
diff --git a/hw/mips/pic32_load_hex.c b/hw/mips/pic32_load_hex.c
new file mode 100644
index 0000000..720c9ee
--- /dev/null
+++ b/hw/mips/pic32_load_hex.c
@@ -0,0 +1,238 @@ 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "pic32_peripherals.h"
+
+/* Macros for converting between hex and binary. */
+#define NIBBLE(x)       (isdigit(x) ? (x)-'0' : tolower(x)+10-'a')
+#define HEX(buffer)     ((NIBBLE((buffer)[0])<<4) + NIBBLE((buffer)[1]))
+
+static unsigned virt_to_phys(unsigned address)
+{
+    if (address >= 0xa0000000 && address <= 0xbfffffff) {
+        return address - 0xa0000000;
+    }
+    if (address >= 0x80000000 && address <= 0x9fffffff) {
+        return address - 0x80000000;
+    }
+    return address;
+}
+
+/*
+ * Read the S record file.
+ */
+static int load_srec(const char *filename,
+    void (*store_byte)(unsigned address, unsigned char byte))
+{
+    FILE *fd;
+    unsigned char buf[256];
+    unsigned char *data;
+    unsigned address;
+    int bytes, output_len;
+
+    fd = fopen(filename, "r");
+    if (!fd) {
+        perror(filename);
+        exit(1);
+    }
+    output_len = 0;
+    while (fgets((char *) buf, sizeof(buf), fd)) {
+        if (buf[0] == '\n') {
+            continue;
+        }
+        if (buf[0] != 'S') {
+            if (output_len == 0) {
+                break;
+            }
+            printf("%s: bad file format\n", filename);
+            exit(1);
+        }
+
+        /* Starting an S-record.  */
+        if (!isxdigit(buf[2]) || !isxdigit(buf[3])) {
+            printf("%s: bad record: %s\n", filename, buf);
+            exit(1);
+        }
+        bytes = HEX(buf + 2);
+
+        /* Ignore the checksum byte.  */
+        --bytes;
+
+        address = 0;
+        data = buf + 4;
+        switch (buf[1]) {
+        case '7':
+            address = HEX(data);
+            data += 2;
+            --bytes;
+            /* Fall through.  */
+        case '8':
+            address = (address << 8) | HEX(data);
+            data += 2;
+            --bytes;
+            /* Fall through.  */
+        case '9':
+            address = (address << 8) | HEX(data);
+            data += 2;
+            address = (address << 8) | HEX(data);
+            data += 2;
+            bytes -= 2;
+            if (bytes == 0) {
+                /*printf("%s: start address = %08x\n", filename, address);*/
+                /* TODO: set start address. */
+            }
+            goto done;
+
+        case '3':
+            address = HEX(data);
+            data += 2;
+            --bytes;
+            /* Fall through.  */
+        case '2':
+            address = (address << 8) | HEX(data);
+            data += 2;
+            --bytes;
+            /* Fall through.  */
+        case '1':
+            address = (address << 8) | HEX(data);
+            data += 2;
+            address = (address << 8) | HEX(data);
+            data += 2;
+            bytes -= 2;
+
+            address = virt_to_phys(address);
+            output_len += bytes;
+            while (bytes-- > 0) {
+                store_byte(address++, HEX(data));
+                data += 2;
+            }
+            break;
+        }
+    }
+done:
+    fclose(fd);
+    return output_len;
+}
+
+/*
+ * Read HEX file.
+ */
+static int load_hex(const char *filename,
+    void (*store_byte)(unsigned address, unsigned char byte))
+{
+    FILE *fd;
+    unsigned char buf[256], data[16], record_type, sum;
+    unsigned address, high;
+    int bytes, output_len, i;
+
+    fd = fopen(filename, "r");
+    if (!fd) {
+        perror(filename);
+        exit(1);
+    }
+    output_len = 0;
+    high = 0;
+    while (fgets((char *) buf, sizeof(buf), fd)) {
+        if (buf[0] == '\n') {
+            continue;
+        }
+        if (buf[0] != ':') {
+            if (output_len == 0) {
+                break;
+            }
+            printf("%s: bad HEX file format\n", filename);
+            exit(1);
+        }
+        if (!isxdigit(buf[1]) || !isxdigit(buf[2]) ||
+            !isxdigit(buf[3]) || !isxdigit(buf[4]) ||
+            !isxdigit(buf[5]) || !isxdigit(buf[6]) ||
+            !isxdigit(buf[7]) || !isxdigit(buf[8])) {
+            printf("%s: bad record: %s\n", filename, buf);
+            exit(1);
+        }
+        record_type = HEX(buf+7);
+        if (record_type == 1) {
+            /* End of file. */
+            break;
+        }
+        bytes = HEX(buf+1);
+        if (strlen((char *) buf) < bytes * 2 + 11) {
+            printf("%s: too short hex line\n", filename);
+            exit(1);
+        }
+        address = high << 16 | HEX(buf+3) << 8 | HEX(buf+5);
+        if (address & 3) {
+            printf("%s: odd address\n", filename);
+            exit(1);
+        }
+
+        sum = 0;
+        for (i = 0; i < bytes; ++i) {
+            data[i] = HEX(buf+9 + i + i);
+            sum += data[i];
+        }
+        sum += record_type + bytes + (address & 0xff) + (address >> 8 & 0xff);
+        if (sum != (unsigned char) -HEX(buf+9 + bytes + bytes)) {
+            printf("%s: bad hex checksum\n", filename);
+            printf("Line %s", buf);
+            exit(1);
+        }
+
+        if (record_type == 5) {
+            /* Start address. */
+            if (bytes != 4) {
+                printf("%s: invalid length of hex start address record: "
+                    "%d bytes\n", filename, bytes);
+                exit(1);
+            }
+            address = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
+            /*printf("%s: start address = %08x\n", filename, address);*/
+            /* TODO: set start address. */
+            continue;
+        }
+        if (record_type == 4) {
+            /* Extended address. */
+            if (bytes != 2) {
+                printf("%s: invalid length of hex linear address record: "
+                    "%d bytes\n", filename, bytes);
+                exit(1);
+            }
+            high = data[0] << 8 | data[1];
+            continue;
+        }
+        if (record_type != 0) {
+            printf("%s: unknown hex record type: %d\n",
+                filename, record_type);
+            exit(1);
+        }
+
+        /* Data record found. */
+        address = virt_to_phys(address);
+        output_len += bytes;
+        for (i = 0; i < bytes; i++) {
+            store_byte(address++, data[i]);
+        }
+    }
+    fclose(fd);
+    return output_len;
+}
+
+int pic32_load_hex_file(const char *filename,
+    void (*store_byte)(unsigned address, unsigned char byte))
+{
+    int memory_len = load_srec(filename, store_byte);
+    if (memory_len == 0) {
+        memory_len = load_hex(filename, store_byte);
+        if (memory_len == 0) {
+            return 0;
+        }
+    }
+    printf("Load file: '%s', %d bytes\n", filename, memory_len);
+    if (qemu_logfile) {
+        fprintf(qemu_logfile, "Load file: '%s', %d bytes\n",
+            filename, memory_len);
+    }
+    return 1;
+}
diff --git a/hw/mips/pic32_peripherals.h b/hw/mips/pic32_peripherals.h
new file mode 100644
index 0000000..4435991
--- /dev/null
+++ b/hw/mips/pic32_peripherals.h
@@ -0,0 +1,210 @@ 
+/*
+ * Define memory map for PIC32 microcontroller.
+ *
+ * Copyright (C) 2015 Serge Vakulenko
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that the copyright notice and this
+ * permission notice and warranty disclaimer appear in supporting
+ * documentation, and that the name of the author not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ *
+ * The author disclaim all warranties with regard to this
+ * software, including all implied warranties of merchantability
+ * and fitness.  In no event shall the author be liable for any
+ * special, indirect or consequential damages or any damages
+ * whatsoever resulting from loss of use, data or profits, whether
+ * in an action of contract, negligence or other tortious action,
+ * arising out of or in connection with the use or performance of
+ * this software.
+ */
+#include "hw/sysbus.h"                  /* SysBusDevice */
+#include "net/net.h"
+
+#define IO_MEM_SIZE     (1024*1024)     /* 1 Mbyte */
+
+typedef struct _uart_t uart_t;
+typedef struct _spi_t spi_t;
+typedef struct _sdcard_t sdcard_t;
+typedef struct _pic32_t pic32_t;
+typedef struct _eth_t eth_t;
+
+/*
+ * UART private data.
+ */
+struct _uart_t {
+    pic32_t     *mcu;                   /* back pointer to pic32 object */
+    unsigned    irq;                    /* interrupt number */
+    int         oactive;                /* output active */
+    unsigned    sta;                    /* UxSTA address */
+    unsigned    mode;                   /* UxMODE address */
+    unsigned    rxbyte;                 /* received byte */
+    CharDriverState *chr;               /* pointer to serial_hds[i] */
+    QEMUTimer   *transmit_timer;        /* needed to delay TX interrupt */
+};
+
+/*
+ * SPI private data.
+ */
+struct _spi_t {
+    unsigned    buf[4];                 /* transmit and receive buffer */
+    unsigned    rfifo;                  /* read fifo counter */
+    unsigned    wfifo;                  /* write fifo counter */
+    unsigned    irq;                    /* interrupt numbers */
+    unsigned    con;                    /* SPIxCON address */
+    unsigned    stat;                   /* SPIxSTAT address */
+};
+
+/*
+ * SD card private data.
+ */
+struct _sdcard_t {
+    const char  *name;                  /* Device name */
+    unsigned    gpio_port;              /* GPIO port number of CS0 signal */
+    unsigned    gpio_cs;                /* GPIO pin mask of CS0 signal */
+    unsigned    kbytes;                 /* Disk size */
+    int         unit;                   /* Index (sd0 or sd1) */
+    int         fd;                     /* Image file */
+    int         select;                 /* Selected */
+    int         read_multiple;          /* Read-multiple mode */
+    unsigned    blen;                   /* Block length */
+    unsigned    wbecnt;                 /* Write block erase count */
+    unsigned    offset;                 /* Read/write offset */
+    unsigned    count;                  /* Byte count */
+    unsigned    limit;                  /* Reply length */
+    unsigned    char buf[1024 + 16];
+};
+
+/*
+ * PIC32 data structure.
+ */
+struct _pic32_t {
+    SysBusDevice parent_obj;
+    MIPSCPU     *cpu;                   /* back pointer to cpu object */
+    uint32_t    *iomem;                 /* backing storage for I/O area */
+
+    int         board_type;             /* board variant */
+    int         stop_on_reset;          /* halt simulation on soft reset */
+    unsigned    syskey_unlock;          /* syskey state */
+
+#define NUM_UART 6                      /* number of UART ports */
+    uart_t      uart[NUM_UART];         /* UART data */
+
+#define NUM_SPI 6                       /* max number of SPI ports */
+    spi_t       spi[NUM_SPI];           /* SPI data */
+
+    unsigned    sdcard_spi_port;        /* SPI port number of SD card */
+    sdcard_t    sdcard[2];              /* SD card data */
+
+    DeviceState *eth_dev;               /* Ethernet device */
+    eth_t       *eth;                   /* Ethernet driver data */
+
+    void (*irq_raise)(pic32_t *s, int irq); /* set interrupt request */
+    void (*irq_clear)(pic32_t *s, int irq); /* clear interrupt request */
+};
+
+/*
+ * GPIO routines.
+ */
+void pic32_gpio_write(pic32_t *s, int unit, unsigned val);
+
+/*
+ * UART routines.
+ */
+void pic32_uart_init(pic32_t *s, int unit, int irq, int sta, int mode);
+unsigned pic32_uart_get_char(pic32_t *s, int unit);
+void pic32_uart_put_char(pic32_t *s, int unit, unsigned char data);
+void pic32_uart_poll_status(pic32_t *s, int unit);
+void pic32_uart_update_mode(pic32_t *s, int unit);
+void pic32_uart_update_status(pic32_t *s, int unit);
+
+/*
+ * SPI routines.
+ */
+void pic32_spi_init(pic32_t *s, int unit, int irq, int con, int stat);
+void pic32_spi_control(pic32_t *s, int unit);
+unsigned pic32_spi_readbuf(pic32_t *s, int unit);
+void pic32_spi_writebuf(pic32_t *s, int unit, unsigned val);
+
+/*
+ * SD card routines.
+ */
+void pic32_sdcard_init(pic32_t *s, int unit, const char *name,
+    const char *filename, int cs_port, int cs_pin);
+void pic32_sdcard_reset(pic32_t *s);
+void pic32_sdcard_select(pic32_t *s, int unit, int on);
+unsigned pic32_sdcard_io(pic32_t *s, unsigned data);
+
+/*
+ * Ethernet routines.
+ */
+void pic32_eth_init(pic32_t *s, NICInfo *nd);
+void pic32_eth_control(pic32_t *s);
+void pic32_mii_command(pic32_t *s);
+void pic32_mii_write(pic32_t *s);
+
+/*
+ * Load a binary file in hex or srec format.
+ */
+int pic32_load_hex_file(const char *filename,
+    void (*store_byte)(unsigned address, unsigned char byte));
+
+/*
+ * Helper defines for i/o switch.
+ */
+#define VALUE(name)     (s->iomem[(name & 0xfffff) >> 2])
+
+#define STORAGE(name)   case name:\
+                            *namep = #name;
+
+#define READONLY(name)  case name:\
+                            *namep = #name;\
+                            goto readonly
+
+#define WRITEOP(name)   case name:\
+                            *namep = #name;\
+                            goto op_##name;\
+                        case name+4:\
+                            *namep = #name"CLR";\
+                            goto op_##name;\
+                        case name+8:\
+                            *namep = #name"SET";\
+                            goto op_##name;\
+                        case name+12:\
+                            *namep = #name"INV";\
+                        op_##name: \
+                            VALUE(name) = write_op(VALUE(name), data, offset)
+
+#define WRITEOPX(name, label) \
+                        case name:\
+                            *namep = #name;\
+                            goto op_##label;\
+                        case name+4:\
+                            *namep = #name"CLR";\
+                            goto op_##label;\
+                        case name+8:\
+                            *namep = #name"SET";\
+                            goto op_##label;\
+                        case name+12:\
+                            *namep = #name"INV";\
+                            goto op_##label
+
+#define WRITEOPR(name, romask) \
+                        case name:\
+                            *namep = #name;\
+                            goto op_##name;\
+                        case name+4:\
+                            *namep = #name"CLR";\
+                            goto op_##name;\
+                        case name+8:\
+                            *namep = #name"SET";\
+                            goto op_##name;\
+                        case name+12:\
+                            *namep = #name"INV";\
+                        op_##name: \
+                            VALUE(name) = (VALUE(name) & (romask)) |\
+                                (write_op(VALUE(name), data, offset) &\
+                                    ~(romask))
diff --git a/hw/mips/pic32_sdcard.c b/hw/mips/pic32_sdcard.c
new file mode 100644
index 0000000..7611233
--- /dev/null
+++ b/hw/mips/pic32_sdcard.c
@@ -0,0 +1,428 @@ 
+/*
+ * SD/MMC card emulation.
+ *
+ * Copyright (C) 2011-2015 Serge Vakulenko
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that the copyright notice and this
+ * permission notice and warranty disclaimer appear in supporting
+ * documentation, and that the name of the author not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ *
+ * The author disclaim all warranties with regard to this
+ * software, including all implied warranties of merchantability
+ * and fitness.  In no event shall the author be liable for any
+ * special, indirect or consequential damages or any damages
+ * whatsoever resulting from loss of use, data or profits, whether
+ * in an action of contract, negligence or other tortious action,
+ * arising out of or in connection with the use or performance of
+ * this software.
+ */
+#include "hw/hw.h"
+#include "pic32_peripherals.h"
+
+/*
+ * Definitions for MMC/SDC commands.
+ */
+#define CMD_GO_IDLE         (0x40+0)    /* CMD0 */
+#define CMD_SEND_OP_SDC     (0x40+41)   /* ACMD41 (SDC) */
+#define CMD_SET_BLEN        (0x40+16)
+#define CMD_SEND_IF_COND    (0x40+8)
+#define CMD_SEND_CSD        (0x40+9)
+#define CMD_STOP            (0x40+12)
+#define CMD_READ_SINGLE     (0x40+17)
+#define CMD_READ_MULTIPLE   (0x40+18)
+#define CMD_SET_WBECNT      (0x40+23)   /* ACMD23 */
+#define CMD_WRITE_SINGLE    (0x40+24)
+#define CMD_WRITE_MULTIPLE  (0x40+25)
+#define CMD_APP             (0x40+55)   /* CMD55 */
+
+#define DATA_START_BLOCK        0xFE    /* start data for single block */
+#define STOP_TRAN_TOKEN         0xFD    /* stop token for write multiple */
+#define WRITE_MULTIPLE_TOKEN    0xFC    /* start data for write multiple */
+
+/*
+ * TODO: add option to enable tracing.
+ */
+#define TRACE   0
+
+static void read_data(int fd, unsigned offset,
+    unsigned char *buf, unsigned blen)
+{
+    int result;
+
+    /* Fill uninitialized blocks by FF: simulate real flash media. */
+    memset(buf, 0xFF, blen);
+
+    result = pread(fd, buf, blen, offset);
+    if (result < 0) {
+        printf("sdcard: pread failed, %u bytes, offset %#x: %s\n",
+            blen, offset, strerror(errno));
+        return;
+    }
+    if (result != blen) {
+        /* Partial file read, return zeroes. */
+        memset(buf, 0, blen);
+    }
+#if 0
+    printf("(%#x)\n", offset);
+    int i, k;
+    for (i = 0; i < blen; i += 32) {
+        for (k = 0; k < 32; k++) {
+            printf(" %02x", buf[i+k]);
+        }
+        printf("\n");
+    }
+#endif
+}
+
+static void write_data(int fd, unsigned offset,
+    unsigned char *buf, unsigned blen)
+{
+    if (pwrite(fd, buf, blen, offset) != blen) {
+        printf("sdcard: pwrite failed, offset %#x\n", offset);
+        return;
+    }
+}
+
+static void card_reset(sdcard_t *d)
+{
+    d->select = 0;
+    d->blen = 512;
+    d->count = 0;
+}
+
+/*
+ * Reset sdcard.
+ */
+void pic32_sdcard_reset(pic32_t *s)
+{
+    card_reset(&s->sdcard[0]);
+    card_reset(&s->sdcard[1]);
+}
+
+/*
+ * Initialize SD card.
+ */
+void pic32_sdcard_init(pic32_t *s, int unit, const char *name,
+    const char *filename, int cs_port, int cs_pin)
+{
+    sdcard_t *d = &s->sdcard[unit];
+    struct stat st;
+
+    memset(d, 0, sizeof(*d));
+    d->name = name;
+    if (!filename) {
+        /* No SD card installed. */
+        return;
+    }
+    d->gpio_port = cs_port;
+    d->gpio_cs = (cs_pin >= 0) ? (1 << cs_pin) : 0;
+
+    d->fd = open(filename, O_RDWR);
+    if (d->fd < 0) {
+        /* Fatal: no image available. */
+        perror(filename);
+        exit(1);
+    }
+    fstat(d->fd, &st);
+    d->kbytes = st.st_size / 1024;
+    printf("Card%u image '%s', %d kbytes\n", unit, filename, d->kbytes);
+    if (qemu_logfile) {
+        fprintf(qemu_logfile, "Card%u image '%s', %d kbytes\n",
+            unit, filename, d->kbytes);
+    }
+}
+
+void pic32_sdcard_select(pic32_t *s, int unit, int on)
+{
+    sdcard_t *d = &s->sdcard[unit];
+
+    if (on) {
+        d->select = 1;
+        d->count = 0;
+    } else {
+        d->select = 0;
+    }
+}
+
+/*
+ * Data i/o: send byte to device.
+ * Return received byte.
+ */
+unsigned pic32_sdcard_io(pic32_t *s, unsigned data)
+{
+    sdcard_t *d = s->sdcard[0].select ? &s->sdcard[0] :
+                  s->sdcard[1].select ? &s->sdcard[1] : 0;
+    unsigned reply;
+
+    if (!d || !d->fd) {
+        /* Unselected i/o. */
+        return 0xFF;
+    }
+    data = (unsigned char) data;
+    reply = 0xFF;
+    if (d->count == 0) {
+        d->buf[0] = data;
+        if (data != 0xFF) {
+            d->count++;
+        }
+    } else {
+        switch (d->buf[0]) {
+        case CMD_GO_IDLE:               /* CMD0: reset */
+            if (d->count >= 7) {
+                break;
+            }
+            d->buf[d->count++] = data;
+            if (d->count == 7) {
+                reply = 0x01;
+            }
+            break;
+        case CMD_APP:                   /* CMD55: application prefix */
+            if (d->count >= 7) {
+                break;
+            }
+            d->buf[d->count++] = data;
+            if (d->count == 7) {
+                reply = 0;
+                d->count = 0;
+            }
+            break;
+        case CMD_SEND_OP_SDC:           /* ACMD41: initialization */
+            if (d->count >= 7) {
+                break;
+            }
+            d->buf[d->count++] = data;
+            if (d->count == 7) {
+                reply = 0;
+            }
+            break;
+        case CMD_SET_BLEN:              /* Set block length */
+            if (d->count >= 7) {
+                break;
+            }
+            d->buf[d->count++] = data;
+            if (d->count == 7) {
+                d->blen = d->buf[1] << 24 | d->buf[2] << 16 |
+                    d->buf[3] << 8 | d->buf[4];
+                if (TRACE) {
+                    fprintf(qemu_logfile,
+                        "--- SD card %d: set block length %u bytes\n",
+                        d->unit, d->blen);
+                }
+                reply = (d->blen > 0 && d->blen <= 1024) ? 0 : 4;
+            }
+            break;
+        case CMD_SET_WBECNT:            /* Set write block erase count */
+            if (d->count >= 7) {
+                break;
+            }
+            d->buf[d->count++] = data;
+            if (d->count == 7) {
+                d->wbecnt = d->buf[1] << 24 | d->buf[2] << 16 |
+                    d->buf[3] << 8 | d->buf[4];
+                if (TRACE) {
+                    fprintf(qemu_logfile,
+                        "--- SD card %d: set write block erase count %u\n",
+                        d->unit, d->wbecnt);
+                }
+                reply = 0;
+                d->count = 0;
+            }
+            break;
+        case CMD_SEND_CSD:              /* Get card data */
+            if (d->count >= 7) {
+                break;
+            }
+            d->buf[d->count++] = data;
+            if (d->count == 7) {
+                /* Send reply */
+                if (TRACE) {
+                    fprintf(qemu_logfile,
+                        "--- SD card %d: send media size %u sectors\n",
+                        d->unit, d->kbytes * 2);
+                }
+                reply = 0;
+                d->limit = 16 + 3;
+                d->count = 1;
+                d->buf[0] = 0;
+                d->buf[1] = DATA_START_BLOCK;
+                d->buf[2+0] = 1 << 6;     /* SDC ver 2.00 */
+                d->buf[2+1] = 0;
+                d->buf[2+2] = 0;
+                d->buf[2+3] = 0;
+                d->buf[2+4] = 0;
+                d->buf[2+5] = 0;
+                d->buf[2+6] = 0;
+                d->buf[2+7] = 0;
+                d->buf[2+8] = (d->kbytes / 512 - 1) >> 8;
+                d->buf[2+9] = d->kbytes / 512 - 1;
+                d->buf[2+10] = 0;
+                d->buf[2+11] = 0;
+                d->buf[2+12] = 0;
+                d->buf[2+13] = 0;
+                d->buf[2+14] = 0;
+                d->buf[2+15] = 0;
+                d->buf[d->limit - 1] = 0xFF;
+                d->buf[d->limit] = 0xFF;
+            }
+            break;
+        case CMD_READ_SINGLE:           /* Read block */
+            if (d->count >= 7) {
+                break;
+            }
+            d->buf[d->count++] = data;
+            if (d->count == 7) {
+                /* Send reply */
+                reply = 0;
+                d->offset = d->buf[1] << 24 | d->buf[2] << 16 |
+                    d->buf[3] << 8 | d->buf[4];
+                if (TRACE) {
+                    fprintf(qemu_logfile,
+                        "--- SD card %d: read offset %#x, length %u bytes\n",
+                        d->unit, d->offset, d->blen);
+                }
+                d->limit = d->blen + 3;
+                d->count = 1;
+                d->buf[0] = 0;
+                d->buf[1] = DATA_START_BLOCK;
+                read_data(d->fd, d->offset, &d->buf[2], d->blen);
+                d->buf[d->limit - 1] = 0xFF;
+                d->buf[d->limit] = 0xFF;
+            }
+            break;
+        case CMD_READ_MULTIPLE:         /* Read multiple blocks */
+            if (d->count >= 7) {
+                break;
+            }
+            d->buf[d->count++] = data;
+            if (d->count == 7) {
+                /* Send reply */
+                reply = 0;
+                d->read_multiple = 1;
+                d->offset = d->buf[1] << 24 | d->buf[2] << 16 |
+                    d->buf[3] << 8 | d->buf[4];
+                if (TRACE) {
+                    fprintf(qemu_logfile,
+                        "--- SD card %d: read offset %#x, length %u bytes\n",
+                        d->unit, d->offset, d->blen);
+                }
+                d->limit = d->blen + 3;
+                d->count = 1;
+                d->buf[0] = 0;
+                d->buf[1] = DATA_START_BLOCK;
+                read_data(d->fd, d->offset, &d->buf[2], d->blen);
+                d->buf[d->limit - 1] = 0xFF;
+                d->buf[d->limit] = 0xFF;
+            }
+            break;
+        case CMD_WRITE_SINGLE:          /* Write block */
+            if (d->count >= sizeof(d->buf)) {
+                break;
+            }
+            d->buf[d->count++] = data;
+            if (d->count == 7) {
+                /* Accept command */
+                reply = 0;
+                d->offset = d->buf[1] << 24 | d->buf[2] << 16 |
+                    d->buf[3] << 8 | d->buf[4];
+                if (TRACE) {
+                    fprintf(qemu_logfile,
+                        "--- SD card %d: write offset %#x\n",
+                        d->unit, d->offset);
+                }
+            } else if (d->count == 7 + d->blen + 2 + 2) {
+                if (d->buf[7] == DATA_START_BLOCK) {
+                    /* Accept data */
+                    reply = 0x05;
+                    d->offset = d->buf[1] << 24 | d->buf[2] << 16 |
+                        d->buf[3] << 8 | d->buf[4];
+                    write_data(d->fd, d->offset, &d->buf[8], d->blen);
+                    if (TRACE) {
+                        fprintf(qemu_logfile,
+                            "--- SD card %d: write data, length %u bytes\n",
+                            d->unit, d->blen);
+                    }
+                } else {
+                    /* Reject data */
+                    reply = 4;
+                    if (TRACE) {
+                        fprintf(qemu_logfile,
+                            "--- SD card %d: reject write data, tag=%02x\n",
+                            d->unit, d->buf[7]);
+                    }
+                }
+            }
+            break;
+        case CMD_WRITE_MULTIPLE:        /* Write multiple blocks */
+            if (d->count >= 7) {
+                break;
+            }
+            d->buf[d->count++] = data;
+            if (d->count == 7) {
+                /* Accept command */
+                reply = 0;
+                d->offset = d->buf[1] << 24 | d->buf[2] << 16 |
+                    d->buf[3] << 8 | d->buf[4];
+                if (TRACE) {
+                    fprintf(qemu_logfile,
+                        "--- SD card %d: write multiple offset %#x\n",
+                        d->unit, d->offset);
+                }
+                d->count = 0;
+            }
+            break;
+        case WRITE_MULTIPLE_TOKEN:      /* Data for write-miltiple */
+            if (d->count >= sizeof(d->buf)) {
+                break;
+            }
+            d->buf[d->count++] = data;
+            if (d->count == 2 + d->blen + 2) {
+                /* Accept data */
+                reply = 0x05;
+                write_data(d->fd, d->offset, &d->buf[1], d->blen);
+                if (TRACE) {
+                    fprintf(qemu_logfile,
+                        "--- SD card %d: write sector %u, length %u bytes\n",
+                        d->unit, d->offset / 512, d->blen);
+                }
+                d->offset += 512;
+                d->count = 0;
+            }
+            break;
+        case CMD_STOP:                  /* Stop read-multiple sequence */
+            if (d->count > 1) {
+                break;
+            }
+            d->read_multiple = 0;
+            reply = 0;
+            break;
+        case CMD_SEND_IF_COND:          /* Stop read-multiple sequence */
+            if (d->count > 1) {
+                break;
+            }
+            d->read_multiple = 0;
+            reply = 4;                  /* Unknown command */
+            break;
+        case 0:                         /* Reply */
+            if (d->count <= d->limit) {
+                reply = d->buf[d->count++];
+                break;
+            }
+            if (d->read_multiple) {
+                /* Next read-multiple block. */
+                d->offset += d->blen;
+                d->count = 1;
+                read_data(d->fd, d->offset, &d->buf[2], d->blen);
+                reply = 0;
+            }
+            break;
+        default:                        /* Ignore */
+            break;
+        }
+    }
+    return reply;
+}
diff --git a/hw/mips/pic32_spi.c b/hw/mips/pic32_spi.c
new file mode 100644
index 0000000..52b1579
--- /dev/null
+++ b/hw/mips/pic32_spi.c
@@ -0,0 +1,121 @@ 
+/*
+ * SPI ports.
+ *
+ * Copyright (C) 2014-2015 Serge Vakulenko
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that the copyright notice and this
+ * permission notice and warranty disclaimer appear in supporting
+ * documentation, and that the name of the author not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ *
+ * The author disclaim all warranties with regard to this
+ * software, including all implied warranties of merchantability
+ * and fitness.  In no event shall the author be liable for any
+ * special, indirect or consequential damages or any damages
+ * whatsoever resulting from loss of use, data or profits, whether
+ * in an action of contract, negligence or other tortious action,
+ * arising out of or in connection with the use or performance of
+ * this software.
+ */
+#include "hw/hw.h"
+#include "pic32_peripherals.h"
+
+#include "pic32mz.h"
+
+#define SPI_IRQ_FAULT   0               /* error irq offset */
+#define SPI_IRQ_TX      1               /* transmitter irq offset */
+#define SPI_IRQ_RX      2               /* receiver irq offset */
+
+unsigned pic32_spi_readbuf(pic32_t *s, int unit)
+{
+    spi_t *p = &s->spi[unit];
+    unsigned result = p->buf[p->rfifo];
+
+    if (VALUE(p->con) & PIC32_SPICON_ENHBUF) {
+        p->rfifo++;
+        p->rfifo &= 3;
+    }
+    if (VALUE(p->stat) & PIC32_SPISTAT_SPIRBF) {
+        VALUE(p->stat) &= ~PIC32_SPISTAT_SPIRBF;
+        /*s->irq_clear(s, p->irq + SPI_IRQ_RX);*/
+    }
+    return result;
+}
+
+void pic32_spi_writebuf(pic32_t *s, int unit, unsigned val)
+{
+    spi_t *p = &s->spi[unit];
+
+    /* Perform SD card i/o on configured SPI port. */
+    if (unit == s->sdcard_spi_port) {
+        unsigned result = 0;
+
+        if (VALUE(p->con) & PIC32_SPICON_MODE32) {
+            /* 32-bit data width */
+            result  = (unsigned char) pic32_sdcard_io(s, val >> 24) << 24;
+            result |= (unsigned char) pic32_sdcard_io(s, val >> 16) << 16;
+            result |= (unsigned char) pic32_sdcard_io(s, val >> 8) << 8;
+            result |= (unsigned char) pic32_sdcard_io(s, val);
+
+        } else if (VALUE(p->con) & PIC32_SPICON_MODE16) {
+            /* 16-bit data width */
+            result = (unsigned char) pic32_sdcard_io(s, val >> 8) << 8;
+            result |= (unsigned char) pic32_sdcard_io(s, val);
+
+        } else {
+            /* 8-bit data width */
+            result = (unsigned char) pic32_sdcard_io(s, val);
+        }
+        p->buf[p->wfifo] = result;
+    } else {
+        /* No device */
+        p->buf[p->wfifo] = ~0;
+    }
+    if (VALUE(p->stat) & PIC32_SPISTAT_SPIRBF) {
+        VALUE(p->stat) |= PIC32_SPISTAT_SPIROV;
+        /*s->irq_raise(s, p->irq + SPI_IRQ_FAULT);*/
+    } else if (VALUE(p->con) & PIC32_SPICON_ENHBUF) {
+        p->wfifo++;
+        p->wfifo &= 3;
+        if (p->wfifo == p->rfifo) {
+            VALUE(p->stat) |= PIC32_SPISTAT_SPIRBF;
+            /*s->irq_raise(s, p->irq + SPI_IRQ_RX);*/
+        }
+    } else {
+        VALUE(p->stat) |= PIC32_SPISTAT_SPIRBF;
+        /*s->irq_raise(s, p->irq + SPI_IRQ_RX);*/
+    }
+}
+
+void pic32_spi_control(pic32_t *s, int unit)
+{
+    spi_t *p = &s->spi[unit];
+
+    if (!(VALUE(p->con) & PIC32_SPICON_ON)) {
+        s->irq_clear(s, p->irq + SPI_IRQ_FAULT);
+        s->irq_clear(s, p->irq + SPI_IRQ_RX);
+        s->irq_clear(s, p->irq + SPI_IRQ_TX);
+        VALUE(p->stat) = PIC32_SPISTAT_SPITBE;
+    } else if (!(VALUE(p->con) & PIC32_SPICON_ENHBUF)) {
+        p->rfifo = 0;
+        p->wfifo = 0;
+    }
+}
+
+/*
+ * Initialize the SPI data structure.
+ */
+void pic32_spi_init(pic32_t *s, int unit, int irq, int con, int stat)
+{
+    spi_t *p = &s->spi[unit];
+
+    p->irq = irq;
+    p->con = con;
+    p->stat = stat;
+    p->rfifo = 0;
+    p->wfifo = 0;
+}
diff --git a/hw/mips/pic32_uart.c b/hw/mips/pic32_uart.c
new file mode 100644
index 0000000..34056cf
--- /dev/null
+++ b/hw/mips/pic32_uart.c
@@ -0,0 +1,228 @@ 
+/*
+ * UART ports.
+ *
+ * Copyright (C) 2014-2015 Serge Vakulenko
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that the copyright notice and this
+ * permission notice and warranty disclaimer appear in supporting
+ * documentation, and that the name of the author not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ *
+ * The author disclaim all warranties with regard to this
+ * software, including all implied warranties of merchantability
+ * and fitness.  In no event shall the author be liable for any
+ * special, indirect or consequential damages or any damages
+ * whatsoever resulting from loss of use, data or profits, whether
+ * in an action of contract, negligence or other tortious action,
+ * arising out of or in connection with the use or performance of
+ * this software.
+ */
+#include "hw/hw.h"
+#include "hw/char/serial.h"
+#include "sysemu/char.h"
+#include "pic32_peripherals.h"
+
+#include "pic32mz.h"
+
+#define UART_IRQ_ERR    0               /* error irq offset */
+#define UART_IRQ_RX     1               /* receiver irq offset */
+#define UART_IRQ_TX     2               /* transmitter irq offset */
+
+/*
+ * Read of UxRXREG register.
+ */
+unsigned pic32_uart_get_char(pic32_t *s, int unit)
+{
+    uart_t *u = &s->uart[unit];
+    unsigned value;
+
+    /* Read a byte from input queue. */
+    value = u->rxbyte;
+    VALUE(u->sta) &= ~PIC32_USTA_URXDA;
+
+    s->irq_clear(s, u->irq + UART_IRQ_RX);
+    return value;
+}
+
+/*
+ * Write to UxTXREG register.
+ */
+void pic32_uart_put_char(pic32_t *s, int unit, unsigned char byte)
+{
+    uart_t *u = &s->uart[unit];
+
+    if (!u->chr) {
+        printf("--- %s(unit = %u) serial port not configured\n",
+            __func__, unit);
+        return;
+    }
+
+    /* Send the byte. */
+    if (qemu_chr_fe_write(u->chr, &byte, 1) != 1) {
+        /* TODO: suspend simulation until serial port ready. */
+        printf("--- %s(unit = %u) failed\n", __func__, unit);
+        return;
+    }
+
+    if ((VALUE(u->mode) & PIC32_UMODE_ON) &&
+        (VALUE(u->sta) & PIC32_USTA_UTXEN))
+    {
+        VALUE(u->sta) |= PIC32_USTA_UTXBF;
+        VALUE(u->sta) &= ~PIC32_USTA_TRMT;
+
+        /* Generate TX interrupt with some delay. */
+        timer_mod(u->transmit_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+            get_ticks_per_sec() / 5000);
+        u->oactive = 1;
+    }
+}
+
+/*
+ * Called before reading a value of UxBRG, UxMODE or UxSTA registers.
+ */
+void pic32_uart_poll_status(pic32_t *s, int unit)
+{
+    uart_t *u = &s->uart[unit];
+
+    /* Keep receiver idle, transmit shift register always empty. */
+    VALUE(u->sta) |= PIC32_USTA_RIDLE;
+
+    /*printf("<%x>", VALUE(u->sta)); fflush(stdout);*/
+}
+
+/*
+ * Write to UxMODE register.
+ */
+void pic32_uart_update_mode(pic32_t *s, int unit)
+{
+    uart_t *u = &s->uart[unit];
+
+    if (!(VALUE(u->mode) & PIC32_UMODE_ON)) {
+        s->irq_clear(s, u->irq + UART_IRQ_RX);
+        s->irq_clear(s, u->irq + UART_IRQ_TX);
+        VALUE(u->sta) &= ~(PIC32_USTA_URXDA | PIC32_USTA_FERR |
+                           PIC32_USTA_PERR | PIC32_USTA_UTXBF);
+        VALUE(u->sta) |= PIC32_USTA_RIDLE | PIC32_USTA_TRMT;
+    }
+}
+
+/*
+ * Write to UxSTA register.
+ */
+void pic32_uart_update_status(pic32_t *s, int unit)
+{
+    uart_t *u = &s->uart[unit];
+
+    if (!(VALUE(u->sta) & PIC32_USTA_URXEN)) {
+        s->irq_clear(s, u->irq + UART_IRQ_RX);
+        VALUE(u->sta) &= ~(PIC32_USTA_URXDA | PIC32_USTA_FERR |
+                           PIC32_USTA_PERR);
+    }
+    if (!(VALUE(u->sta) & PIC32_USTA_UTXEN)) {
+        s->irq_clear(s, u->irq + UART_IRQ_TX);
+        VALUE(u->sta) &= ~PIC32_USTA_UTXBF;
+        VALUE(u->sta) |= PIC32_USTA_TRMT;
+    }
+}
+
+/*
+ * Return a number of free bytes in the receive FIFO.
+ */
+static int uart_can_receive(void *opaque)
+{
+    uart_t *u = opaque;
+    pic32_t *s = u->mcu;        /* used in VALUE() */
+
+    /*printf("--- %s(%p) called\n", __func__, u);*/
+
+    if (!(VALUE(u->mode) & PIC32_UMODE_ON) ||
+        !(VALUE(u->sta) & PIC32_USTA_URXEN)) {
+        /* UART disabled. */
+        return 0;
+    }
+
+    if (VALUE(u->sta) & PIC32_USTA_URXDA) {
+        /* Receive buffer full. */
+        return 0;
+    }
+    return 1;
+}
+
+/*
+ * Process the received data.
+ */
+static void uart_receive(void *opaque, const uint8_t *buf, int size)
+{
+    uart_t *u = opaque;
+    pic32_t *s = u->mcu;        /* used in VALUE() */
+
+    /*printf("--- %s(%p) called\n", __func__, u);*/
+    if (!(VALUE(u->mode) & PIC32_UMODE_ON) ||
+        !(VALUE(u->sta) & PIC32_USTA_URXEN)) {
+        /* UART disabled. */
+        return;
+    }
+
+    if (VALUE(u->sta) & PIC32_USTA_URXDA) {
+        /* Receive buffer full. */
+        return;
+    }
+
+    u->rxbyte = buf[0];
+    VALUE(u->sta) |= PIC32_USTA_URXDA;
+
+    /* Activate receive interrupt. */
+    s->irq_raise(s, u->irq + UART_IRQ_RX);
+}
+
+/*
+ * Activate the transmit interrupt.
+ */
+static void uart_timeout(void *opaque)
+{
+    uart_t *u = opaque;
+    pic32_t *s = u->mcu;        /* used in VALUE() */
+
+    /*printf("--- %s() called\n", __func__);*/
+    if (u->oactive) {
+        /* Activate transmit interrupt. */
+        /*printf("uart%u: raise tx irq %u\n", unit, u->irq + UART_IRQ_TX);*/
+        if ((VALUE(u->mode) & PIC32_UMODE_ON) &&
+            (VALUE(u->sta) & PIC32_USTA_UTXEN)) {
+            s->irq_raise(s, u->irq + UART_IRQ_TX);
+        }
+        VALUE(u->sta) &= ~PIC32_USTA_UTXBF;
+        VALUE(u->sta) |= PIC32_USTA_TRMT;
+        u->oactive = 0;
+    }
+}
+
+/*
+ * Initialize the UART data structure.
+ */
+void pic32_uart_init(pic32_t *s, int unit, int irq, int sta, int mode)
+{
+    uart_t *u = &s->uart[unit];
+
+    u->mcu = s;
+    u->irq = irq;
+    u->sta = sta;
+    u->mode = mode;
+    u->transmit_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, uart_timeout, u);
+
+    if (unit >= MAX_SERIAL_PORTS) {
+        /* Cannot instantiate so many serial ports. */
+        u->chr = 0;
+        return;
+    }
+    u->chr = serial_hds[unit];
+
+    /* Setup callback functions. */
+    if (u->chr) {
+        qemu_chr_add_handlers(u->chr, uart_can_receive, uart_receive, NULL, u);
+    }
+}
diff --git a/hw/mips/pic32mx.h b/hw/mips/pic32mx.h
new file mode 100644
index 0000000..c0433fd
--- /dev/null
+++ b/hw/mips/pic32mx.h
@@ -0,0 +1,1290 @@ 
+/*
+ * Hardware register defines for Microchip PIC32MX microcontrollers.
+ *
+ * Copyright (C) 2010 Serge Vakulenko
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that the copyright notice and this
+ * permission notice and warranty disclaimer appear in supporting
+ * documentation, and that the name of the author not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ *
+ * The author disclaim all warranties with regard to this
+ * software, including all implied warranties of merchantability
+ * and fitness.  In no event shall the author be liable for any
+ * special, indirect or consequential damages or any damages
+ * whatsoever resulting from loss of use, data or profits, whether
+ * in an action of contract, negligence or other tortious action,
+ * arising out of or in connection with the use or performance of
+ * this software.
+ */
+#ifndef _IO_PIC32MX_H
+#define _IO_PIC32MX_H
+
+/*--------------------------------------
+ * Peripheral registers.
+ */
+#define PIC32_R(a)              (a)
+
+/*--------------------------------------
+ * UART registers.
+ */
+#define U1MODE          PIC32_R(0x6000) /* Mode */
+#define U1MODECLR       PIC32_R(0x6004)
+#define U1MODESET       PIC32_R(0x6008)
+#define U1MODEINV       PIC32_R(0x600C)
+#define U1STA           PIC32_R(0x6010) /* Status and control */
+#define U1STACLR        PIC32_R(0x6014)
+#define U1STASET        PIC32_R(0x6018)
+#define U1STAINV        PIC32_R(0x601C)
+#define U1TXREG         PIC32_R(0x6020) /* Transmit */
+#define U1RXREG         PIC32_R(0x6030) /* Receive */
+#define U1BRG           PIC32_R(0x6040) /* Baud rate */
+#define U1BRGCLR        PIC32_R(0x6044)
+#define U1BRGSET        PIC32_R(0x6048)
+#define U1BRGINV        PIC32_R(0x604C)
+
+#ifdef PIC32MX4
+#define U2MODE          PIC32_R(0x6200) /* Mode */
+#define U2MODECLR       PIC32_R(0x6204)
+#define U2MODESET       PIC32_R(0x6208)
+#define U2MODEINV       PIC32_R(0x620C)
+#define U2STA           PIC32_R(0x6210) /* Status and control */
+#define U2STACLR        PIC32_R(0x6214)
+#define U2STASET        PIC32_R(0x6218)
+#define U2STAINV        PIC32_R(0x621C)
+#define U2TXREG         PIC32_R(0x6220) /* Transmit */
+#define U2RXREG         PIC32_R(0x6230) /* Receive */
+#define U2BRG           PIC32_R(0x6240) /* Baud rate */
+#define U2BRGCLR        PIC32_R(0x6244)
+#define U2BRGSET        PIC32_R(0x6248)
+#define U2BRGINV        PIC32_R(0x624C)
+#endif
+#ifdef PIC32MX7
+#define U4MODE          PIC32_R(0x6200) /* Mode */
+#define U4MODECLR       PIC32_R(0x6204)
+#define U4MODESET       PIC32_R(0x6208)
+#define U4MODEINV       PIC32_R(0x620C)
+#define U4STA           PIC32_R(0x6210) /* Status and control */
+#define U4STACLR        PIC32_R(0x6214)
+#define U4STASET        PIC32_R(0x6218)
+#define U4STAINV        PIC32_R(0x621C)
+#define U4TXREG         PIC32_R(0x6220) /* Transmit */
+#define U4RXREG         PIC32_R(0x6230) /* Receive */
+#define U4BRG           PIC32_R(0x6240) /* Baud rate */
+#define U4BRGCLR        PIC32_R(0x6244)
+#define U4BRGSET        PIC32_R(0x6248)
+#define U4BRGINV        PIC32_R(0x624C)
+
+#define U3MODE          PIC32_R(0x6400) /* Mode */
+#define U3MODECLR       PIC32_R(0x6404)
+#define U3MODESET       PIC32_R(0x6408)
+#define U3MODEINV       PIC32_R(0x640C)
+#define U3STA           PIC32_R(0x6410) /* Status and control */
+#define U3STACLR        PIC32_R(0x6414)
+#define U3STASET        PIC32_R(0x6418)
+#define U3STAINV        PIC32_R(0x641C)
+#define U3TXREG         PIC32_R(0x6420) /* Transmit */
+#define U3RXREG         PIC32_R(0x6430) /* Receive */
+#define U3BRG           PIC32_R(0x6440) /* Baud rate */
+#define U3BRGCLR        PIC32_R(0x6444)
+#define U3BRGSET        PIC32_R(0x6448)
+#define U3BRGINV        PIC32_R(0x644C)
+
+#define U6MODE          PIC32_R(0x6600) /* Mode */
+#define U6MODECLR       PIC32_R(0x6604)
+#define U6MODESET       PIC32_R(0x6608)
+#define U6MODEINV       PIC32_R(0x660C)
+#define U6STA           PIC32_R(0x6610) /* Status and control */
+#define U6STACLR        PIC32_R(0x6614)
+#define U6STASET        PIC32_R(0x6618)
+#define U6STAINV        PIC32_R(0x661C)
+#define U6TXREG         PIC32_R(0x6620) /* Transmit */
+#define U6RXREG         PIC32_R(0x6630) /* Receive */
+#define U6BRG           PIC32_R(0x6640) /* Baud rate */
+#define U6BRGCLR        PIC32_R(0x6644)
+#define U6BRGSET        PIC32_R(0x6648)
+#define U6BRGINV        PIC32_R(0x664C)
+
+#define U2MODE          PIC32_R(0x6800) /* Mode */
+#define U2MODECLR       PIC32_R(0x6804)
+#define U2MODESET       PIC32_R(0x6808)
+#define U2MODEINV       PIC32_R(0x680C)
+#define U2STA           PIC32_R(0x6810) /* Status and control */
+#define U2STACLR        PIC32_R(0x6814)
+#define U2STASET        PIC32_R(0x6818)
+#define U2STAINV        PIC32_R(0x681C)
+#define U2TXREG         PIC32_R(0x6820) /* Transmit */
+#define U2RXREG         PIC32_R(0x6830) /* Receive */
+#define U2BRG           PIC32_R(0x6840) /* Baud rate */
+#define U2BRGCLR        PIC32_R(0x6844)
+#define U2BRGSET        PIC32_R(0x6848)
+#define U2BRGINV        PIC32_R(0x684C)
+
+#define U5MODE          PIC32_R(0x6A00) /* Mode */
+#define U5MODECLR       PIC32_R(0x6A04)
+#define U5MODESET       PIC32_R(0x6A08)
+#define U5MODEINV       PIC32_R(0x6A0C)
+#define U5STA           PIC32_R(0x6A10) /* Status and control */
+#define U5STACLR        PIC32_R(0x6A14)
+#define U5STASET        PIC32_R(0x6A18)
+#define U5STAINV        PIC32_R(0x6A1C)
+#define U5TXREG         PIC32_R(0x6A20) /* Transmit */
+#define U5RXREG         PIC32_R(0x6A30) /* Receive */
+#define U5BRG           PIC32_R(0x6A40) /* Baud rate */
+#define U5BRGCLR        PIC32_R(0x6A44)
+#define U5BRGSET        PIC32_R(0x6A48)
+#define U5BRGINV        PIC32_R(0x6A4C)
+#endif
+
+/*
+ * UART Mode register.
+ */
+#define PIC32_UMODE_STSEL       0x0001  /* 2 Stop bits */
+#define PIC32_UMODE_PDSEL       0x0006  /* Bitmask: */
+#define PIC32_UMODE_PDSEL_8NPAR 0x0000  /* 8-bit data, no parity */
+#define PIC32_UMODE_PDSEL_8EVEN 0x0002  /* 8-bit data, even parity */
+#define PIC32_UMODE_PDSEL_8ODD  0x0004  /* 8-bit data, odd parity */
+#define PIC32_UMODE_PDSEL_9NPAR 0x0006  /* 9-bit data, no parity */
+#define PIC32_UMODE_BRGH        0x0008  /* High Baud Rate Enable */
+#define PIC32_UMODE_RXINV       0x0010  /* Receive Polarity Inversion */
+#define PIC32_UMODE_ABAUD       0x0020  /* Auto-Baud Enable */
+#define PIC32_UMODE_LPBACK      0x0040  /* UARTx Loopback Mode */
+#define PIC32_UMODE_WAKE        0x0080  /* Wake-up on start in Sleep Mode */
+#define PIC32_UMODE_UEN         0x0300  /* Bitmask: */
+#define PIC32_UMODE_UEN_RTS     0x0100  /* Using UxRTS pin */
+#define PIC32_UMODE_UEN_RTSCTS  0x0200  /* Using UxCTS and UxRTS pins */
+#define PIC32_UMODE_UEN_BCLK    0x0300  /* Using UxBCLK pin */
+#define PIC32_UMODE_RTSMD       0x0800  /* UxRTS Pin Simplex mode */
+#define PIC32_UMODE_IREN        0x1000  /* IrDA Encoder/Decoder Enable bit */
+#define PIC32_UMODE_SIDL        0x2000  /* Stop in Idle Mode */
+#define PIC32_UMODE_FRZ         0x4000  /* Freeze in Debug Exception Mode */
+#define PIC32_UMODE_ON          0x8000  /* UART Enable */
+
+/*
+ * UART Control and status register.
+ */
+#define PIC32_USTA_URXDA        0x00000001 /* Receive Data Available (ro) */
+#define PIC32_USTA_OERR         0x00000002 /* Receive Buffer Overrun */
+#define PIC32_USTA_FERR         0x00000004 /* Framing error detected (ro) */
+#define PIC32_USTA_PERR         0x00000008 /* Parity error detected (ro) */
+#define PIC32_USTA_RIDLE        0x00000010 /* Receiver is idle (ro) */
+#define PIC32_USTA_ADDEN        0x00000020 /* Address Detect mode */
+#define PIC32_USTA_URXISEL      0x000000C0 /* Bitmask: RX interrupt when... */
+#define PIC32_USTA_URXISEL_NEMP 0x00000000 /* ...receive buffer is not empty */
+#define PIC32_USTA_URXISEL_HALF 0x00000040 /* ...receive buffer 1/2 full */
+#define PIC32_USTA_URXISEL_3_4  0x00000080 /* ...receive buffer 3/4 full */
+#define PIC32_USTA_TRMT         0x00000100 /* TX shift register empty (ro) */
+#define PIC32_USTA_UTXBF        0x00000200 /* Transmit buffer is full (ro) */
+#define PIC32_USTA_UTXEN        0x00000400 /* Transmit Enable */
+#define PIC32_USTA_UTXBRK       0x00000800 /* Transmit Break */
+#define PIC32_USTA_URXEN        0x00001000 /* Receiver Enable */
+#define PIC32_USTA_UTXINV       0x00002000 /* Transmit Polarity Inversion */
+#define PIC32_USTA_UTXISEL      0x0000C000 /* Bitmask: TX interrupt when... */
+#define PIC32_USTA_UTXISEL_1    0x00000000 /* ...at least 1 empty space */
+#define PIC32_USTA_UTXISEL_ALL  0x00004000 /* ...all characters transmitted */
+#define PIC32_USTA_UTXISEL_EMP  0x00008000 /* ...the TX buffer becomes empty */
+#define PIC32_USTA_ADDR         0x00FF0000 /* Automatic Address Mask */
+#define PIC32_USTA_ADM_EN       0x01000000 /* Automatic Address Detect */
+
+/*
+ * Compute the 16-bit baud rate divisor, given
+ * the bus frequency and baud rate.
+ * Round to the nearest integer.
+ */
+#define PIC32_BRG_BAUD(fr, bd)  ((((fr)/8 + (bd)) / (bd) / 2) - 1)
+
+/*--------------------------------------
+ * Port A-G registers.
+ */
+#define TRISA           PIC32_R(0x86000) /* Port A: mask of inputs */
+#define TRISACLR        PIC32_R(0x86004)
+#define TRISASET        PIC32_R(0x86008)
+#define TRISAINV        PIC32_R(0x8600C)
+#define PORTA           PIC32_R(0x86010) /* A: read inputs, write outputs */
+#define PORTACLR        PIC32_R(0x86014)
+#define PORTASET        PIC32_R(0x86018)
+#define PORTAINV        PIC32_R(0x8601C)
+#define LATA            PIC32_R(0x86020) /* A: read/write outputs */
+#define LATACLR         PIC32_R(0x86024)
+#define LATASET         PIC32_R(0x86028)
+#define LATAINV         PIC32_R(0x8602C)
+#define ODCA            PIC32_R(0x86030) /* A: open drain configuration */
+#define ODCACLR         PIC32_R(0x86034)
+#define ODCASET         PIC32_R(0x86038)
+#define ODCAINV         PIC32_R(0x8603C)
+
+#define TRISB           PIC32_R(0x86040) /* Port B: mask of inputs */
+#define TRISBCLR        PIC32_R(0x86044)
+#define TRISBSET        PIC32_R(0x86048)
+#define TRISBINV        PIC32_R(0x8604C)
+#define PORTB           PIC32_R(0x86050) /* B: read inputs, write outputs */
+#define PORTBCLR        PIC32_R(0x86054)
+#define PORTBSET        PIC32_R(0x86058)
+#define PORTBINV        PIC32_R(0x8605C)
+#define LATB            PIC32_R(0x86060) /* B: read/write outputs */
+#define LATBCLR         PIC32_R(0x86064)
+#define LATBSET         PIC32_R(0x86068)
+#define LATBINV         PIC32_R(0x8606C)
+#define ODCB            PIC32_R(0x86070) /* B: open drain configuration */
+#define ODCBCLR         PIC32_R(0x86074)
+#define ODCBSET         PIC32_R(0x86078)
+#define ODCBINV         PIC32_R(0x8607C)
+
+#define TRISC           PIC32_R(0x86080) /* Port C: mask of inputs */
+#define TRISCCLR        PIC32_R(0x86084)
+#define TRISCSET        PIC32_R(0x86088)
+#define TRISCINV        PIC32_R(0x8608C)
+#define PORTC           PIC32_R(0x86090) /* C: read inputs, write outputs */
+#define PORTCCLR        PIC32_R(0x86094)
+#define PORTCSET        PIC32_R(0x86098)
+#define PORTCINV        PIC32_R(0x8609C)
+#define LATC            PIC32_R(0x860A0) /* C: read/write outputs */
+#define LATCCLR         PIC32_R(0x860A4)
+#define LATCSET         PIC32_R(0x860A8)
+#define LATCINV         PIC32_R(0x860AC)
+#define ODCC            PIC32_R(0x860B0) /* C: open drain configuration */
+#define ODCCCLR         PIC32_R(0x860B4)
+#define ODCCSET         PIC32_R(0x860B8)
+#define ODCCINV         PIC32_R(0x860BC)
+
+#define TRISD           PIC32_R(0x860C0) /* Port D: mask of inputs */
+#define TRISDCLR        PIC32_R(0x860C4)
+#define TRISDSET        PIC32_R(0x860C8)
+#define TRISDINV        PIC32_R(0x860CC)
+#define PORTD           PIC32_R(0x860D0) /* D: read inputs, write outputs */
+#define PORTDCLR        PIC32_R(0x860D4)
+#define PORTDSET        PIC32_R(0x860D8)
+#define PORTDINV        PIC32_R(0x860DC)
+#define LATD            PIC32_R(0x860E0) /* D: read/write outputs */
+#define LATDCLR         PIC32_R(0x860E4)
+#define LATDSET         PIC32_R(0x860E8)
+#define LATDINV         PIC32_R(0x860EC)
+#define ODCD            PIC32_R(0x860F0) /* D: open drain configuration */
+#define ODCDCLR         PIC32_R(0x860F4)
+#define ODCDSET         PIC32_R(0x860F8)
+#define ODCDINV         PIC32_R(0x860FC)
+
+#define TRISE           PIC32_R(0x86100) /* Port E: mask of inputs */
+#define TRISECLR        PIC32_R(0x86104)
+#define TRISESET        PIC32_R(0x86108)
+#define TRISEINV        PIC32_R(0x8610C)
+#define PORTE           PIC32_R(0x86110) /* E: read inputs, write outputs */
+#define PORTECLR        PIC32_R(0x86114)
+#define PORTESET        PIC32_R(0x86118)
+#define PORTEINV        PIC32_R(0x8611C)
+#define LATE            PIC32_R(0x86120) /* E: read/write outputs */
+#define LATECLR         PIC32_R(0x86124)
+#define LATESET         PIC32_R(0x86128)
+#define LATEINV         PIC32_R(0x8612C)
+#define ODCE            PIC32_R(0x86130) /* E: open drain configuration */
+#define ODCECLR         PIC32_R(0x86134)
+#define ODCESET         PIC32_R(0x86138)
+#define ODCEINV         PIC32_R(0x8613C)
+
+#define TRISF           PIC32_R(0x86140) /* Port F: mask of inputs */
+#define TRISFCLR        PIC32_R(0x86144)
+#define TRISFSET        PIC32_R(0x86148)
+#define TRISFINV        PIC32_R(0x8614C)
+#define PORTF           PIC32_R(0x86150) /* F: read inputs, write outputs */
+#define PORTFCLR        PIC32_R(0x86154)
+#define PORTFSET        PIC32_R(0x86158)
+#define PORTFINV        PIC32_R(0x8615C)
+#define LATF            PIC32_R(0x86160) /* F: read/write outputs */
+#define LATFCLR         PIC32_R(0x86164)
+#define LATFSET         PIC32_R(0x86168)
+#define LATFINV         PIC32_R(0x8616C)
+#define ODCF            PIC32_R(0x86170) /* F: open drain configuration */
+#define ODCFCLR         PIC32_R(0x86174)
+#define ODCFSET         PIC32_R(0x86178)
+#define ODCFINV         PIC32_R(0x8617C)
+
+#define TRISG           PIC32_R(0x86180) /* Port G: mask of inputs */
+#define TRISGCLR        PIC32_R(0x86184)
+#define TRISGSET        PIC32_R(0x86188)
+#define TRISGINV        PIC32_R(0x8618C)
+#define PORTG           PIC32_R(0x86190) /* G: read inputs, write outputs */
+#define PORTGCLR        PIC32_R(0x86194)
+#define PORTGSET        PIC32_R(0x86198)
+#define PORTGINV        PIC32_R(0x8619C)
+#define LATG            PIC32_R(0x861A0) /* G: read/write outputs */
+#define LATGCLR         PIC32_R(0x861A4)
+#define LATGSET         PIC32_R(0x861A8)
+#define LATGINV         PIC32_R(0x861AC)
+#define ODCG            PIC32_R(0x861B0) /* G: open drain configuration */
+#define ODCGCLR         PIC32_R(0x861B4)
+#define ODCGSET         PIC32_R(0x861B8)
+#define ODCGINV         PIC32_R(0x861BC)
+
+#define CNCON           PIC32_R(0x861C0) /* Interrupt-on-change control */
+#define CNCONCLR        PIC32_R(0x861C4)
+#define CNCONSET        PIC32_R(0x861C8)
+#define CNCONINV        PIC32_R(0x861CC)
+#define CNEN            PIC32_R(0x861D0) /* Input change interrupt enable */
+#define CNENCLR         PIC32_R(0x861D4)
+#define CNENSET         PIC32_R(0x861D8)
+#define CNENINV         PIC32_R(0x861DC)
+#define CNPUE           PIC32_R(0x861E0) /* Input pin pull-up enable */
+#define CNPUECLR        PIC32_R(0x861E4)
+#define CNPUESET        PIC32_R(0x861E8)
+#define CNPUEINV        PIC32_R(0x861EC)
+
+/*--------------------------------------
+ * A/D Converter registers.
+ */
+#define AD1CON1         PIC32_R(0x9000) /* Control register 1 */
+#define AD1CON1CLR      PIC32_R(0x9004)
+#define AD1CON1SET      PIC32_R(0x9008)
+#define AD1CON1INV      PIC32_R(0x900C)
+#define AD1CON2         PIC32_R(0x9010) /* Control register 2 */
+#define AD1CON2CLR      PIC32_R(0x9014)
+#define AD1CON2SET      PIC32_R(0x9018)
+#define AD1CON2INV      PIC32_R(0x901C)
+#define AD1CON3         PIC32_R(0x9020) /* Control register 3 */
+#define AD1CON3CLR      PIC32_R(0x9024)
+#define AD1CON3SET      PIC32_R(0x9028)
+#define AD1CON3INV      PIC32_R(0x902C)
+#define AD1CHS          PIC32_R(0x9040) /* Channel select */
+#define AD1CHSCLR       PIC32_R(0x9044)
+#define AD1CHSSET       PIC32_R(0x9048)
+#define AD1CHSINV       PIC32_R(0x904C)
+#define AD1CSSL         PIC32_R(0x9050) /* Input scan selection */
+#define AD1CSSLCLR      PIC32_R(0x9054)
+#define AD1CSSLSET      PIC32_R(0x9058)
+#define AD1CSSLINV      PIC32_R(0x905C)
+#define AD1PCFG         PIC32_R(0x9060) /* Port configuration */
+#define AD1PCFGCLR      PIC32_R(0x9064)
+#define AD1PCFGSET      PIC32_R(0x9068)
+#define AD1PCFGINV      PIC32_R(0x906C)
+#define ADC1BUF0        PIC32_R(0x9070) /* Result words */
+#define ADC1BUF1        PIC32_R(0x9080)
+#define ADC1BUF2        PIC32_R(0x9090)
+#define ADC1BUF3        PIC32_R(0x90A0)
+#define ADC1BUF4        PIC32_R(0x90B0)
+#define ADC1BUF5        PIC32_R(0x90C0)
+#define ADC1BUF6        PIC32_R(0x90D0)
+#define ADC1BUF7        PIC32_R(0x90E0)
+#define ADC1BUF8        PIC32_R(0x90F0)
+#define ADC1BUF9        PIC32_R(0x9100)
+#define ADC1BUFA        PIC32_R(0x9110)
+#define ADC1BUFB        PIC32_R(0x9120)
+#define ADC1BUFC        PIC32_R(0x9130)
+#define ADC1BUFD        PIC32_R(0x9140)
+#define ADC1BUFE        PIC32_R(0x9150)
+#define ADC1BUFF        PIC32_R(0x9160)
+
+/*--------------------------------------
+ * Parallel master port registers.
+ */
+#define PMCON           PIC32_R(0x7000) /* Control */
+#define PMCONCLR        PIC32_R(0x7004)
+#define PMCONSET        PIC32_R(0x7008)
+#define PMCONINV        PIC32_R(0x700C)
+#define PMMODE          PIC32_R(0x7010) /* Mode */
+#define PMMODECLR       PIC32_R(0x7014)
+#define PMMODESET       PIC32_R(0x7018)
+#define PMMODEINV       PIC32_R(0x701C)
+#define PMADDR          PIC32_R(0x7020) /* Address */
+#define PMADDRCLR       PIC32_R(0x7024)
+#define PMADDRSET       PIC32_R(0x7028)
+#define PMADDRINV       PIC32_R(0x702C)
+#define PMDOUT          PIC32_R(0x7030) /* Data output */
+#define PMDOUTCLR       PIC32_R(0x7034)
+#define PMDOUTSET       PIC32_R(0x7038)
+#define PMDOUTINV       PIC32_R(0x703C)
+#define PMDIN           PIC32_R(0x7040) /* Data input */
+#define PMDINCLR        PIC32_R(0x7044)
+#define PMDINSET        PIC32_R(0x7048)
+#define PMDININV        PIC32_R(0x704C)
+#define PMAEN           PIC32_R(0x7050) /* Pin enable */
+#define PMAENCLR        PIC32_R(0x7054)
+#define PMAENSET        PIC32_R(0x7058)
+#define PMAENINV        PIC32_R(0x705C)
+#define PMSTAT          PIC32_R(0x7060) /* Status (slave only) */
+#define PMSTATCLR       PIC32_R(0x7064)
+#define PMSTATSET       PIC32_R(0x7068)
+#define PMSTATINV       PIC32_R(0x706C)
+
+/*
+ * PMP Control register.
+ */
+#define PIC32_PMCON_RDSP        0x0001 /* Read strobe polarity active-high */
+#define PIC32_PMCON_WRSP        0x0002 /* Write strobe polarity active-high */
+#define PIC32_PMCON_CS1P        0x0008 /* Chip select 0 polarity active-high */
+#define PIC32_PMCON_CS2P        0x0010 /* Chip select 1 polarity active-high */
+#define PIC32_PMCON_ALP         0x0020 /* Address latch polarity active-high */
+#define PIC32_PMCON_CSF         0x00C0 /* Chip select function bitmask: */
+#define PIC32_PMCON_CSF_NONE    0x0000 /* PMCS2 and PMCS1 as A[15:14] */
+#define PIC32_PMCON_CSF_CS2     0x0040 /* PMCS2 as chip select */
+#define PIC32_PMCON_CSF_CS21    0x0080 /* PMCS2 and PMCS1 as chip select */
+#define PIC32_PMCON_PTRDEN      0x0100 /* Read/write strobe port enable */
+#define PIC32_PMCON_PTWREN      0x0200 /* Write enable strobe port enable */
+#define PIC32_PMCON_PMPTTL      0x0400 /* TTL input buffer select */
+#define PIC32_PMCON_ADRMUX      0x1800 /* Address/data mux selection: */
+#define PIC32_PMCON_ADRMUX_NONE 0x0000 /* Address and data separate */
+#define PIC32_PMCON_ADRMUX_AD   0x0800 /* Lower address on PMD[7:0],
+                                        * high on PMA[15:8] */
+#define PIC32_PMCON_ADRMUX_D8   0x1000 /* All address on PMD[7:0] */
+#define PIC32_PMCON_ADRMUX_D16  0x1800 /* All address on PMD[15:0] */
+#define PIC32_PMCON_SIDL        0x2000 /* Stop in idle */
+#define PIC32_PMCON_FRZ         0x4000 /* Freeze in debug exception */
+#define PIC32_PMCON_ON          0x8000 /* Parallel master port enable */
+
+/*
+ * PMP Mode register.
+ */
+#define PIC32_PMMODE_WAITE(x)   ((x)<<0) /* Wait states: data hold
+                                          * after RW strobe */
+#define PIC32_PMMODE_WAITM(x)   ((x)<<2) /* Wait states: data RW strobe */
+#define PIC32_PMMODE_WAITB(x)   ((x)<<6) /* Wait states: data setup
+                                          * to RW strobe */
+#define PIC32_PMMODE_MODE       0x0300  /* Mode select bitmask: */
+#define PIC32_PMMODE_MODE_SLAVE 0x0000  /* Legacy slave */
+#define PIC32_PMMODE_MODE_SLENH 0x0100  /* Enhanced slave */
+#define PIC32_PMMODE_MODE_MAST2 0x0200  /* Master mode 2 */
+#define PIC32_PMMODE_MODE_MAST1 0x0300  /* Master mode 1 */
+#define PIC32_PMMODE_MODE16     0x0400  /* 16-bit mode */
+#define PIC32_PMMODE_INCM       0x1800  /* Address increment mode bitmask: */
+#define PIC32_PMMODE_INCM_NONE  0x0000  /* No increment/decrement */
+#define PIC32_PMMODE_INCM_INC   0x0800  /* Increment address */
+#define PIC32_PMMODE_INCM_DEC   0x1000  /* Decrement address */
+#define PIC32_PMMODE_INCM_SLAVE 0x1800  /* Slave auto-increment */
+#define PIC32_PMMODE_IRQM       0x6000  /* Interrupt request bitmask: */
+#define PIC32_PMMODE_IRQM_DIS   0x0000  /* No interrupt generated */
+#define PIC32_PMMODE_IRQM_END   0x2000  /* Interrupt at end of R/W cycle */
+#define PIC32_PMMODE_IRQM_A3    0x4000  /* Interrupt on address 3 */
+#define PIC32_PMMODE_BUSY       0x8000  /* Port is busy */
+
+/*
+ * PMP Address register.
+ */
+#define PIC32_PMADDR_PADDR      0x3FFF /* Destination address */
+#define PIC32_PMADDR_CS1        0x4000 /* Chip select 1 is active */
+#define PIC32_PMADDR_CS2        0x8000 /* Chip select 2 is active */
+
+/*
+ * PMP status register (slave only).
+ */
+#define PIC32_PMSTAT_OB0E       0x0001 /* Output buffer 0 empty */
+#define PIC32_PMSTAT_OB1E       0x0002 /* Output buffer 1 empty */
+#define PIC32_PMSTAT_OB2E       0x0004 /* Output buffer 2 empty */
+#define PIC32_PMSTAT_OB3E       0x0008 /* Output buffer 3 empty */
+#define PIC32_PMSTAT_OBUF       0x0040 /* Output buffer underflow */
+#define PIC32_PMSTAT_OBE        0x0080 /* Output buffer empty */
+#define PIC32_PMSTAT_IB0F       0x0100 /* Input buffer 0 full */
+#define PIC32_PMSTAT_IB1F       0x0200 /* Input buffer 1 full */
+#define PIC32_PMSTAT_IB2F       0x0400 /* Input buffer 2 full */
+#define PIC32_PMSTAT_IB3F       0x0800 /* Input buffer 3 full */
+#define PIC32_PMSTAT_IBOV       0x4000 /* Input buffer overflow */
+#define PIC32_PMSTAT_IBF        0x8000 /* Input buffer full */
+
+/*--------------------------------------
+ * USB registers.
+ */
+#define U1OTGIR         PIC32_R(0x85040) /* OTG interrupt flags */
+#define U1OTGIE         PIC32_R(0x85050) /* OTG interrupt enable */
+#define U1OTGSTAT       PIC32_R(0x85060) /* Comparator and pin status */
+#define U1OTGCON        PIC32_R(0x85070) /* Resistor and pin control */
+#define U1PWRC          PIC32_R(0x85080) /* Power control */
+#define U1IR            PIC32_R(0x85200) /* Pending interrupt */
+#define U1IE            PIC32_R(0x85210) /* Interrupt enable */
+#define U1EIR           PIC32_R(0x85220) /* Pending error interrupt */
+#define U1EIE           PIC32_R(0x85230) /* Error interrupt enable */
+#define U1STAT          PIC32_R(0x85240) /* Status FIFO */
+#define U1CON           PIC32_R(0x85250) /* Control */
+#define U1ADDR          PIC32_R(0x85260) /* Address */
+#define U1BDTP1         PIC32_R(0x85270) /* Buffer descriptor table ptr 1 */
+#define U1FRML          PIC32_R(0x85280) /* Frame counter low */
+#define U1FRMH          PIC32_R(0x85290) /* Frame counter high */
+#define U1TOK           PIC32_R(0x852A0) /* Host control */
+#define U1SOF           PIC32_R(0x852B0) /* SOF counter */
+#define U1BDTP2         PIC32_R(0x852C0) /* Buffer descriptor table ptr 2 */
+#define U1BDTP3         PIC32_R(0x852D0) /* Buffer descriptor table ptr 3 */
+#define U1CNFG1         PIC32_R(0x852E0) /* Debug and idle */
+#define U1EP(n)         PIC32_R(0x85300 + (n << 4)) /* Endpoint control */
+
+/*
+ * USB Control register.
+ */
+#define PIC32_U1CON_USBEN       0x0001 /* USB module enable (device mode) */
+#define PIC32_U1CON_SOFEN       0x0001 /* SOF sent every 1 ms (host mode) */
+#define PIC32_U1CON_PPBRST      0x0002 /* Ping-pong buffers reset */
+#define PIC32_U1CON_RESUME      0x0004 /* Resume signaling enable */
+#define PIC32_U1CON_HOSTEN      0x0008 /* Host mode enable */
+#define PIC32_U1CON_USBRST      0x0010 /* USB reset */
+#define PIC32_U1CON_PKTDIS      0x0020 /* Packet transfer disable */
+#define PIC32_U1CON_TOKBUSY     0x0020 /* Token busy indicator */
+#define PIC32_U1CON_SE0         0x0040 /* Single ended zero detected */
+#define PIC32_U1CON_JSTATE      0x0080 /* Live diff.receiver JSTATE flag */
+
+/*
+ * USB Power control register.
+ */
+#define PIC32_U1PWRC_USBPWR     0x0001 /* USB operation enable */
+#define PIC32_U1PWRC_USUSPEND   0x0002 /* USB suspend mode */
+#define PIC32_U1PWRC_USLPGRD    0x0010 /* USB sleep entry guard */
+#define PIC32_U1PWRC_UACTPND    0x0080 /* UAB activity pending */
+
+/*
+ * USB Pending interrupt register.
+ * USB Interrupt enable register.
+ */
+#define PIC32_U1I_DETACH        0x0001 /* Detach (host mode) */
+#define PIC32_U1I_URST          0x0001 /* USB reset (device mode) */
+#define PIC32_U1I_UERR          0x0002 /* USB error condition */
+#define PIC32_U1I_SOF           0x0004 /* SOF token  */
+#define PIC32_U1I_TRN           0x0008 /* Token processing complete */
+#define PIC32_U1I_IDLE          0x0010 /* Idle detect */
+#define PIC32_U1I_RESUME        0x0020 /* Resume */
+#define PIC32_U1I_ATTACH        0x0040 /* Peripheral attach */
+#define PIC32_U1I_STALL         0x0080 /* STALL handshake */
+
+/*
+ * USB OTG interrupt flags register.
+ * USB OTG interrupt enable register.
+ */
+#define PIC32_U1OTGI_VBUSVD     0x0001 /* A-device Vbus change */
+#define PIC32_U1OTGI_SESEND     0x0004 /* B-device Vbus change */
+#define PIC32_U1OTGI_SESVD      0x0008 /* Session valid change */
+#define PIC32_U1OTGI_ACTV       0x0010 /* Bus activity indicator */
+#define PIC32_U1OTGI_LSTATE     0x0020 /* Line state stable */
+#define PIC32_U1OTGI_T1MSEC     0x0040 /* 1 millisecond timer expired */
+#define PIC32_U1OTGI_ID         0x0080 /* ID state change */
+
+#define PIC32_U1OTGSTAT_VBUSVD  0x0001 /*  */
+#define PIC32_U1OTGSTAT_SESEND  0x0004 /*  */
+#define PIC32_U1OTGSTAT_SESVD   0x0008 /*  */
+#define PIC32_U1OTGSTAT_LSTATE  0x0020 /*  */
+#define PIC32_U1OTGSTAT_ID      0x0080 /*  */
+
+#define PIC32_U1OTGCON_VBUSDIS  0x0001 /*  */
+#define PIC32_U1OTGCON_VBUSCHG  0x0002 /*  */
+#define PIC32_U1OTGCON_OTGEN    0x0004 /*  */
+#define PIC32_U1OTGCON_VBUSON   0x0008 /*  */
+#define PIC32_U1OTGCON_DMPULDWN 0x0010 /*  */
+#define PIC32_U1OTGCON_DPPULDWN 0x0020 /*  */
+#define PIC32_U1OTGCON_DMPULUP  0x0040 /*  */
+#define PIC32_U1OTGCON_DPPULUP  0x0080 /*  */
+
+#define PIC32_U1EI_PID          0x0001 /*  */
+#define PIC32_U1EI_CRC5         0x0002 /*  */
+#define PIC32_U1EI_EOF          0x0002 /*  */
+#define PIC32_U1EI_CRC16        0x0004 /*  */
+#define PIC32_U1EI_DFN8         0x0008 /*  */
+#define PIC32_U1EI_BTO          0x0010 /*  */
+#define PIC32_U1EI_DMA          0x0020 /*  */
+#define PIC32_U1EI_BMX          0x0040 /*  */
+#define PIC32_U1EI_BTS          0x0080 /*  */
+
+#define PIC32_U1STAT_PPBI       0x0004 /*  */
+#define PIC32_U1STAT_DIR        0x0008 /*  */
+#define PIC32_U1STAT_ENDPT(x)   (((x) >> 4) & 0xF) /*  */
+
+#define PIC32_U1ADDR_DEVADDR    0x007F /*  */
+#define PIC32_U1ADDR_USBADDR0   0x0001 /*  */
+#define PIC32_U1ADDR_DEVADDR1   0x0002 /*  */
+#define PIC32_U1ADDR_DEVADDR2   0x0004 /*  */
+#define PIC32_U1ADDR_DEVADDR3   0x0008 /*  */
+#define PIC32_U1ADDR_DEVADDR4   0x0010 /*  */
+#define PIC32_U1ADDR_DEVADDR5   0x0020 /*  */
+#define PIC32_U1ADDR_DEVADDR6   0x0040 /*  */
+#define PIC32_U1ADDR_LSPDEN     0x0080 /*  */
+
+#define PIC32_U1FRML_FRM0       0x0001 /*  */
+#define PIC32_U1FRML_FRM1       0x0002 /*  */
+#define PIC32_U1FRML_FRM2       0x0004 /*  */
+#define PIC32_U1FRML_FRM3       0x0008 /*  */
+#define PIC32_U1FRML_FRM4       0x0010 /*  */
+#define PIC32_U1FRML_FRM5       0x0020 /*  */
+#define PIC32_U1FRML_FRM6       0x0040 /*  */
+#define PIC32_U1FRML_FRM7       0x0080 /*  */
+
+#define PIC32_U1FRMH_FRM8       0x0001 /*  */
+#define PIC32_U1FRMH_FRM9       0x0002 /*  */
+#define PIC32_U1FRMH_FRM10      0x0004 /*  */
+
+#define PIC32_U1TOK_EP0         0x0001 /*  */
+#define PIC32_U1TOK_EP          0x000F /*  */
+#define PIC32_U1TOK_EP1         0x0002 /*  */
+#define PIC32_U1TOK_EP2         0x0004 /*  */
+#define PIC32_U1TOK_EP3         0x0008 /*  */
+#define PIC32_U1TOK_PID0        0x0010 /*  */
+#define PIC32_U1TOK_PID         0x00F0 /*  */
+#define PIC32_U1TOK_PID1        0x0020 /*  */
+#define PIC32_U1TOK_PID2        0x0040 /*  */
+#define PIC32_U1TOK_PID3        0x0080 /*  */
+
+#define PIC32_U1CNFG1_USBSIDL   0x0010 /*  */
+#define PIC32_U1CNFG1_USBFRZ    0x0020 /*  */
+#define PIC32_U1CNFG1_UOEMON    0x0040 /*  */
+#define PIC32_U1CNFG1_UTEYE     0x0080 /*  */
+
+#define PIC32_U1EP_EPHSHK       0x0001 /*  */
+#define PIC32_U1EP_EPSTALL      0x0002 /*  */
+#define PIC32_U1EP_EPTXEN       0x0004 /*  */
+#define PIC32_U1EP_EPRXEN       0x0008 /*  */
+#define PIC32_U1EP_EPCONDIS     0x0010 /*  */
+#define PIC32_U1EP_RETRYDIS     0x0040 /*  */
+#define PIC32_U1EP_LSPD         0x0080 /*  */
+
+/* DB status field values */
+#define PIC32_DB_BSTALL         (1 << 2)
+#define PIC32_DB_DTS            (1 << 3)
+#define PIC32_DB_NINC           (1 << 4)
+#define PIC32_DB_KEEP           (1 << 5)
+#define PIC32_DB_DATA1          (1 << 6)
+#define PIC32_DB_UOWN           (1 << 7)
+#define PIC32_DB_GET_PID(x)     (((x) >> 2) & 0xF)
+#define PIC32_DB_SET_PID(x)     (((x) & 0xF) << 2)
+#define PIC32_DB_GET_COUNT(x)   (((x) >> 16) & 0x3FF)
+#define PIC32_DB_SET_COUNT(x)   (((x) & 0x3FF) << 16)
+
+/*--------------------------------------
+ * SPI registers.
+ */
+#ifdef PIC32MX4
+#define SPI1CON         PIC32_R(0x5800) /* Control */
+#define SPI1CONCLR      PIC32_R(0x5804)
+#define SPI1CONSET      PIC32_R(0x5808)
+#define SPI1CONINV      PIC32_R(0x580C)
+#define SPI1STAT        PIC32_R(0x5810) /* Status */
+#define SPI1STATCLR     PIC32_R(0x5814)
+#define SPI1STATSET     PIC32_R(0x5818)
+#define SPI1STATINV     PIC32_R(0x581C)
+#define SPI1BUF         PIC32_R(0x5820) /* Transmit and receive buffer */
+#define SPI1BRG         PIC32_R(0x5830) /* Baud rate generator */
+#define SPI1BRGCLR      PIC32_R(0x5834)
+#define SPI1BRGSET      PIC32_R(0x5838)
+#define SPI1BRGINV      PIC32_R(0x583C)
+#endif
+#ifdef PIC32MX7
+#define SPI3CON         PIC32_R(0x5800) /* Control */
+#define SPI3CONCLR      PIC32_R(0x5804)
+#define SPI3CONSET      PIC32_R(0x5808)
+#define SPI3CONINV      PIC32_R(0x580C)
+#define SPI3STAT        PIC32_R(0x5810) /* Status */
+#define SPI3STATCLR     PIC32_R(0x5814)
+#define SPI3STATSET     PIC32_R(0x5818)
+#define SPI3STATINV     PIC32_R(0x581C)
+#define SPI3BUF         PIC32_R(0x5820) /* Transmit and receive buffer */
+#define SPI3BRG         PIC32_R(0x5830) /* Baud rate generator */
+#define SPI3BRGCLR      PIC32_R(0x5834)
+#define SPI3BRGSET      PIC32_R(0x5838)
+#define SPI3BRGINV      PIC32_R(0x583C)
+
+#define SPI4CON         PIC32_R(0x5C00) /* Control */
+#define SPI4CONCLR      PIC32_R(0x5C04)
+#define SPI4CONSET      PIC32_R(0x5C08)
+#define SPI4CONINV      PIC32_R(0x5C0C)
+#define SPI4STAT        PIC32_R(0x5C10) /* Status */
+#define SPI4STATCLR     PIC32_R(0x5C14)
+#define SPI4STATSET     PIC32_R(0x5C18)
+#define SPI4STATINV     PIC32_R(0x5C1C)
+#define SPI4BUF         PIC32_R(0x5C20) /* Transmit and receive buffer */
+#define SPI4BRG         PIC32_R(0x5C30) /* Baud rate generator */
+#define SPI4BRGCLR      PIC32_R(0x5C34)
+#define SPI4BRGSET      PIC32_R(0x5C38)
+#define SPI4BRGINV      PIC32_R(0x5C3C)
+
+#define SPI1CON         PIC32_R(0x5E00) /* Control */
+#define SPI1CONCLR      PIC32_R(0x5E04)
+#define SPI1CONSET      PIC32_R(0x5E08)
+#define SPI1CONINV      PIC32_R(0x5E0C)
+#define SPI1STAT        PIC32_R(0x5E10) /* Status */
+#define SPI1STATCLR     PIC32_R(0x5E14)
+#define SPI1STATSET     PIC32_R(0x5E18)
+#define SPI1STATINV     PIC32_R(0x5E1C)
+#define SPI1BUF         PIC32_R(0x5E20) /* Transmit and receive buffer */
+#define SPI1BRG         PIC32_R(0x5E30) /* Baud rate generator */
+#define SPI1BRGCLR      PIC32_R(0x5E34)
+#define SPI1BRGSET      PIC32_R(0x5E38)
+#define SPI1BRGINV      PIC32_R(0x5E3C)
+#endif
+
+#define SPI2CON         PIC32_R(0x5A00) /* Control */
+#define SPI2CONCLR      PIC32_R(0x5A04)
+#define SPI2CONSET      PIC32_R(0x5A08)
+#define SPI2CONINV      PIC32_R(0x5A0C)
+#define SPI2STAT        PIC32_R(0x5A10) /* Status */
+#define SPI2STATCLR     PIC32_R(0x5A14)
+#define SPI2STATSET     PIC32_R(0x5A18)
+#define SPI2STATINV     PIC32_R(0x5A1C)
+#define SPI2BUF         PIC32_R(0x5A20) /* Transmit and receive buffer */
+#define SPI2BRG         PIC32_R(0x5A30) /* Baud rate generator */
+#define SPI2BRGCLR      PIC32_R(0x5A34)
+#define SPI2BRGSET      PIC32_R(0x5A38)
+#define SPI2BRGINV      PIC32_R(0x5A3C)
+
+/*
+ * SPI Control register.
+ */
+#define PIC32_SPICON_MSTEN      0x00000020      /* Master mode */
+#define PIC32_SPICON_CKP        0x00000040      /* Idle clock is high level */
+#define PIC32_SPICON_SSEN       0x00000080      /* Slave mode: SSx pin enable */
+#define PIC32_SPICON_CKE        0x00000100      /* Output data changes on
+                                                 * transition from active clock
+                                                 * state to Idle clock state */
+#define PIC32_SPICON_SMP        0x00000200      /* Master mode: input sampled
+                                                 * at end of data output time */
+#define PIC32_SPICON_MODE16     0x00000400      /* 16-bit data width */
+#define PIC32_SPICON_MODE32     0x00000800      /* 32-bit data width */
+#define PIC32_SPICON_DISSDO     0x00001000      /* SDOx pin is not used */
+#define PIC32_SPICON_SIDL       0x00002000      /* Stop in Idle mode */
+#define PIC32_SPICON_FRZ        0x00004000      /* Freeze in Debug mode */
+#define PIC32_SPICON_ON         0x00008000      /* SPI Peripheral is enabled */
+#define PIC32_SPICON_ENHBUF     0x00010000      /* Enhanced buffer enable */
+#define PIC32_SPICON_SPIFE      0x00020000      /* Frame synchronization pulse
+                                                 * is the first bit clock */
+#define PIC32_SPICON_FRMPOL     0x20000000      /* Frame pulse active-high */
+#define PIC32_SPICON_FRMSYNC    0x40000000      /* Frame sync pulse input */
+#define PIC32_SPICON_FRMEN      0x80000000      /* Framed SPI support */
+
+/*
+ * SPI Status register.
+ */
+#define PIC32_SPISTAT_SPIRBF    0x00000001      /* Receive buffer is full */
+#define PIC32_SPISTAT_SPITBF    0x00000002      /* Transmit buffer is full */
+#define PIC32_SPISTAT_SPITBE    0x00000008      /* Transmit buffer is empty */
+#define PIC32_SPISTAT_SPIRBE    0x00000020      /* Receive buffer is empty */
+#define PIC32_SPISTAT_SPIROV    0x00000040      /* Receive overflow flag */
+#define PIC32_SPISTAT_SPIBUSY   0x00000800      /* SPI is busy */
+
+/*--------------------------------------
+ * DMA controller registers.
+ */
+#define DMACON          PIC32_R(0x83000)       /* DMA Control */
+#define DMACONCLR       PIC32_R(0x83004)
+#define DMACONSET       PIC32_R(0x83008)
+#define DMACONINV       PIC32_R(0x8300C)
+#define DMASTAT         PIC32_R(0x83010)       /* DMA Status */
+#define DMAADDR         PIC32_R(0x83020)       /* DMA Address */
+/* TODO: other DMA registers. */
+
+/*--------------------------------------
+ * System controller registers.
+ */
+#define OSCCON          PIC32_R(0xf000)
+#define OSCCONCLR       PIC32_R(0xf004)
+#define OSCCONSET       PIC32_R(0xf008)
+#define OSCCONINV       PIC32_R(0xf00c)
+#define OSCTUN          PIC32_R(0xf010)
+#define OSCTUNCLR       PIC32_R(0xf014)
+#define OSCTUNSET       PIC32_R(0xf018)
+#define OSCTUNINV       PIC32_R(0xf01c)
+#define DDPCON          PIC32_R(0xf200)        /* Debug Data Port Control */
+#define DEVID           PIC32_R(0xf220)
+#define SYSKEY          PIC32_R(0xf230)
+#define RCON            PIC32_R(0xf600)
+#define RCONCLR         PIC32_R(0xf604)
+#define RCONSET         PIC32_R(0xf608)
+#define RCONINV         PIC32_R(0xf60C)
+#define RSWRST          PIC32_R(0xf610)
+#define RSWRSTCLR       PIC32_R(0xf614)
+#define RSWRSTSET       PIC32_R(0xf618)
+#define RSWRSTINV       PIC32_R(0xf61C)
+
+/*
+ * Oscillator control register.
+ */
+#define PIC32_OSCCON_UNUSED     0xc0a08800
+#define PIC32_OSCCON_OSWEN      0x00000001
+#define PIC32_OSCCON_SOSCEN     0x00000002
+#define PIC32_OSCCON_UFRCEN     0x00000004
+#define PIC32_OSCCON_CF         0x00000008
+#define PIC32_OSCCON_SLPEN      0x00000010
+#define PIC32_OSCCON_SLOCK      0x00000020
+#define PIC32_OSCCON_ULOCK      0x00000040
+#define PIC32_OSCCON_CLKLOCK    0x00000080
+#define PIC32_OSCCON_NOSC       0x00000700
+#define PIC32_OSCCON_COSC       0x00007000
+#define PIC32_OSCCON_PLLMULT    0x00070000
+#define PIC32_OSCCON_PBDIV      0x00180000
+#define PIC32_OSCCON_SOSCRDY    0x00400000
+#define PIC32_OSCCON_FRCDIV     0x07000000
+#define PIC32_OSCCON_PLLODIV    0x38000000
+
+/*
+ * Oscillator tune register.
+ */
+#define PIC32_OSCTUN_UNUSED     0xffffffc0
+#define PIC32_OSCTUN_TUN        0x0000003f
+
+/*
+ * Reset control register.
+ */
+#define PIC32_RCON_UNUSED       0xfffffc20
+#define PIC32_RCON_POR          0x00000001
+#define PIC32_RCON_BOR          0x00000002
+#define PIC32_RCON_IDLE         0x00000004
+#define PIC32_RCON_SLEEP        0x00000008
+#define PIC32_RCON_WDTO         0x00000010
+#define PIC32_RCON_SWR          0x00000040
+#define PIC32_RCON_EXTR         0x00000080
+#define PIC32_RCON_VREGS        0x00000100
+#define PIC32_RCON_CMR          0x00000200
+
+/*--------------------------------------
+ * Prefetch cache controller registers.
+ */
+#define CHECON          PIC32_R(0x84000)       /* Prefetch cache control */
+#define CHECONCLR       PIC32_R(0x84004)
+#define CHECONSET       PIC32_R(0x84008)
+#define CHECONINV       PIC32_R(0x8400C)
+/* TODO: other prefetch registers */
+
+/*--------------------------------------
+ * Bus matrix control registers.
+ */
+#define BMXCON          PIC32_R(0x82000)       /* Memory configuration */
+#define BMXCONCLR       PIC32_R(0x82004)
+#define BMXCONSET       PIC32_R(0x82008)
+#define BMXCONINV       PIC32_R(0x8200C)
+#define BMXDKPBA        PIC32_R(0x82010)       /* Data RAM kernel program
+                                                * base address */
+#define BMXDUDBA        PIC32_R(0x82020)       /* Data RAM user data BA */
+#define BMXDUPBA        PIC32_R(0x82030)       /* Data RAM user program BA */
+#define BMXDRMSZ        PIC32_R(0x82040)       /* Data RAM size */
+#define BMXPUPBA        PIC32_R(0x82050)       /* Program Flash user program */
+#define BMXPFMSZ        PIC32_R(0x82060)       /* Program Flash size */
+#define BMXBOOTSZ       PIC32_R(0x82070)       /* Boot Flash size */
+
+/*--------------------------------------
+ * Non-volatile memory control registers.
+ */
+#define NVMCON          PIC32_R(0x0F400)
+#define NVMCONCLR       PIC32_R(0x0F404)
+#define NVMCONSET       PIC32_R(0x0F408)
+#define NVMCONINV       PIC32_R(0x0F40C)
+#define NVMKEY          PIC32_R(0x0F410)
+#define NVMADDR         PIC32_R(0x0F420)
+#define NVMADDRCLR      PIC32_R(0x0F424)
+#define NVMADDRSET      PIC32_R(0x0F428)
+#define NVMADDRINV      PIC32_R(0x0F42C)
+#define NVMDATA         PIC32_R(0x0F430)
+#define NVMSRCADDR      PIC32_R(0x0F440)
+
+#define PIC32_NVMCON_NVMOP      0x0000000F
+#define PIC32_NVMCON_NOP                 0 /* No operation */
+#define PIC32_NVMCON_WORD_PGM            1 /* Word program */
+#define PIC32_NVMCON_ROW_PGM             3 /* Row program */
+#define PIC32_NVMCON_PAGE_ERASE          4 /* Page erase */
+
+#define PIC32_NVMCON_LVDSTAT    0x00000800
+#define PIC32_NVMCON_LVDERR     0x00001000
+#define PIC32_NVMCON_WRERR      0x00002000
+#define PIC32_NVMCON_WREN       0x00004000
+#define PIC32_NVMCON_WR         0x00008000
+
+/*
+ * Timer2 registers
+ */
+#define T2CON           PIC32_R(0x0800)
+#define T2CONSET        PIC32_R(0x0808)
+#define TMR2            PIC32_R(0x0810)
+#define PR2             PIC32_R(0x0820)
+
+/*
+ * Output compare registers
+ */
+#define OC1CON          PIC32_R(0x3000)
+#define OC1R            PIC32_R(0x3010)
+#define OC1RS           PIC32_R(0x3020)
+#define OC4CON          PIC32_R(0x3600)
+#define OC4R            PIC32_R(0x3610)
+#define OC4RS           PIC32_R(0x3620)
+
+/*
+ * Watchdog registers
+ */
+#define WDTCON          PIC32_R(0x0000)    /* Watchdog timer control */
+#define WDTCONCLR       PIC32_R(0x0004)
+#define WDTCONSET       PIC32_R(0x0008)
+
+/*--------------------------------------
+ * Configuration registers.
+ */
+#define DEVCFG0         0x9fc02ffc
+#define DEVCFG1         0x9fc02ff8
+#define DEVCFG2         0x9fc02ff4
+#define DEVCFG3         0x9fc02ff0
+
+/*
+ * Config0 register at 1fc02ffc, inverted.
+ */
+#define DEVCFG0_DEBUG_MASK      0x00000003 /* Debugger enable bits */
+#define DEVCFG0_DEBUG_DISABLED  0x00000000 /* Debugger disabled */
+#define DEVCFG0_DEBUG_ENABLED   0x00000002 /* Debugger enabled */
+#define DEVCFG0_ICESEL          0x00000008 /* Use PGC1/PGD1
+                                            * (default PGC2/PGD2) */
+#define DEVCFG0_PWP_MASK        0x000ff000 /* Program flash write protect */
+#define DEVCFG0_BWP             0x01000000 /* Boot flash write protect */
+#define DEVCFG0_CP              0x10000000 /* Code protect */
+
+/*
+ * Config1 register at 1fc02ff8.
+ */
+#define DEVCFG1_UNUSED          0xff600858
+#define DEVCFG1_FNOSC_MASK      0x00000007 /* Oscillator selection */
+#define DEVCFG1_FNOSC_FRC       0x00000000 /* Fast RC */
+#define DEVCFG1_FNOSC_FRCDIVPLL 0x00000001 /* Fast RC with div-by-N and PLL */
+#define DEVCFG1_FNOSC_PRI       0x00000002 /* Primary oscillator XT, HS, EC */
+#define DEVCFG1_FNOSC_PRIPLL    0x00000003 /* Primary with PLL */
+#define DEVCFG1_FNOSC_SEC       0x00000004 /* Secondary oscillator */
+#define DEVCFG1_FNOSC_LPRC      0x00000005 /* Low-power RC */
+#define DEVCFG1_FNOSC_FRCDIV    0x00000007 /* Fast RC with divide-by-N */
+#define DEVCFG1_FSOSCEN         0x00000020 /* Secondary oscillator enable */
+#define DEVCFG1_IESO            0x00000080 /* Internal-external switch over */
+#define DEVCFG1_POSCMOD_MASK    0x00000300 /* Primary oscillator config */
+#define DEVCFG1_POSCMOD_EXT     0x00000000 /* External mode */
+#define DEVCFG1_POSCMOD_XT      0x00000100 /* XT oscillator */
+#define DEVCFG1_POSCMOD_HS      0x00000200 /* HS oscillator */
+#define DEVCFG1_POSCMOD_DISABLE 0x00000300 /* Disabled */
+#define DEVCFG1_OSCIOFNC        0x00000400 /* CLKO output active */
+#define DEVCFG1_FPBDIV_MASK     0x00003000 /* Peripheral bus clock divisor */
+#define DEVCFG1_FPBDIV_1        0x00000000 /* SYSCLK / 1 */
+#define DEVCFG1_FPBDIV_2        0x00001000 /* SYSCLK / 2 */
+#define DEVCFG1_FPBDIV_4        0x00002000 /* SYSCLK / 4 */
+#define DEVCFG1_FPBDIV_8        0x00003000 /* SYSCLK / 8 */
+#define DEVCFG1_FCKM_DISABLE    0x00004000 /* Fail-safe clk monitor disable */
+#define DEVCFG1_FCKS_DISABLE    0x00008000 /* Clock switching disable */
+#define DEVCFG1_WDTPS_MASK      0x001f0000 /* Watchdog postscale */
+#define DEVCFG1_WDTPS_1         0x00000000 /* 1:1 */
+#define DEVCFG1_WDTPS_2         0x00010000 /* 1:2 */
+#define DEVCFG1_WDTPS_4         0x00020000 /* 1:4 */
+#define DEVCFG1_WDTPS_8         0x00030000 /* 1:8 */
+#define DEVCFG1_WDTPS_16        0x00040000 /* 1:16 */
+#define DEVCFG1_WDTPS_32        0x00050000 /* 1:32 */
+#define DEVCFG1_WDTPS_64        0x00060000 /* 1:64 */
+#define DEVCFG1_WDTPS_128       0x00070000 /* 1:128 */
+#define DEVCFG1_WDTPS_256       0x00080000 /* 1:256 */
+#define DEVCFG1_WDTPS_512       0x00090000 /* 1:512 */
+#define DEVCFG1_WDTPS_1024      0x000a0000 /* 1:1024 */
+#define DEVCFG1_WDTPS_2048      0x000b0000 /* 1:2048 */
+#define DEVCFG1_WDTPS_4096      0x000c0000 /* 1:4096 */
+#define DEVCFG1_WDTPS_8192      0x000d0000 /* 1:8192 */
+#define DEVCFG1_WDTPS_16384     0x000e0000 /* 1:16384 */
+#define DEVCFG1_WDTPS_32768     0x000f0000 /* 1:32768 */
+#define DEVCFG1_WDTPS_65536     0x00100000 /* 1:65536 */
+#define DEVCFG1_WDTPS_131072    0x00110000 /* 1:131072 */
+#define DEVCFG1_WDTPS_262144    0x00120000 /* 1:262144 */
+#define DEVCFG1_WDTPS_524288    0x00130000 /* 1:524288 */
+#define DEVCFG1_WDTPS_1048576   0x00140000 /* 1:1048576 */
+#define DEVCFG1_FWDTEN          0x00800000 /* Watchdog enable */
+
+/*
+ * Config2 register at 1fc02ff4.
+ */
+#define DEVCFG2_UNUSED          0xfff87888
+#define DEVCFG2_FPLLIDIV_MASK   0x00000007 /* PLL input divider */
+#define DEVCFG2_FPLLIDIV_1      0x00000000 /* 1x */
+#define DEVCFG2_FPLLIDIV_2      0x00000001 /* 2x */
+#define DEVCFG2_FPLLIDIV_3      0x00000002 /* 3x */
+#define DEVCFG2_FPLLIDIV_4      0x00000003 /* 4x */
+#define DEVCFG2_FPLLIDIV_5      0x00000004 /* 5x */
+#define DEVCFG2_FPLLIDIV_6      0x00000005 /* 6x */
+#define DEVCFG2_FPLLIDIV_10     0x00000006 /* 10x */
+#define DEVCFG2_FPLLIDIV_12     0x00000007 /* 12x */
+#define DEVCFG2_FPLLMUL_MASK    0x00000070 /* PLL multiplier */
+#define DEVCFG2_FPLLMUL_15      0x00000000 /* 15x */
+#define DEVCFG2_FPLLMUL_16      0x00000010 /* 16x */
+#define DEVCFG2_FPLLMUL_17      0x00000020 /* 17x */
+#define DEVCFG2_FPLLMUL_18      0x00000030 /* 18x */
+#define DEVCFG2_FPLLMUL_19      0x00000040 /* 19x */
+#define DEVCFG2_FPLLMUL_20      0x00000050 /* 20x */
+#define DEVCFG2_FPLLMUL_21      0x00000060 /* 21x */
+#define DEVCFG2_FPLLMUL_24      0x00000070 /* 24x */
+#define DEVCFG2_UPLLIDIV_MASK   0x00000700 /* USB PLL input divider */
+#define DEVCFG2_UPLLIDIV_1      0x00000000 /* 1x */
+#define DEVCFG2_UPLLIDIV_2      0x00000100 /* 2x */
+#define DEVCFG2_UPLLIDIV_3      0x00000200 /* 3x */
+#define DEVCFG2_UPLLIDIV_4      0x00000300 /* 4x */
+#define DEVCFG2_UPLLIDIV_5      0x00000400 /* 5x */
+#define DEVCFG2_UPLLIDIV_6      0x00000500 /* 6x */
+#define DEVCFG2_UPLLIDIV_10     0x00000600 /* 10x */
+#define DEVCFG2_UPLLIDIV_12     0x00000700 /* 12x */
+#define DEVCFG2_UPLLDIS         0x00008000 /* Disable USB PLL */
+#define DEVCFG2_FPLLODIV_MASK   0x00070000 /* Default postscaler for PLL */
+#define DEVCFG2_FPLLODIV_1      0x00000000 /* 1x */
+#define DEVCFG2_FPLLODIV_2      0x00010000 /* 2x */
+#define DEVCFG2_FPLLODIV_4      0x00020000 /* 4x */
+#define DEVCFG2_FPLLODIV_8      0x00030000 /* 8x */
+#define DEVCFG2_FPLLODIV_16     0x00040000 /* 16x */
+#define DEVCFG2_FPLLODIV_32     0x00050000 /* 32x */
+#define DEVCFG2_FPLLODIV_64     0x00060000 /* 64x */
+#define DEVCFG2_FPLLODIV_256    0x00070000 /* 256x */
+
+/*
+ * Config3 register at 1fc02ff0.
+ */
+#define DEVCFG3_UNUSED          0x38f80000
+#define DEVCFG3_USERID_MASK     0x0000ffff /* User-defined ID */
+#define DEVCFG3_USERID(x)       ((x) & 0xffff)
+#define DEVCFG3_FSRSSEL_MASK    0x00070000 /* SRS select */
+#define DEVCFG3_FSRSSEL_ALL     0x00000000 /* All irqs use a shadow set */
+#define DEVCFG3_FSRSSEL_1       0x00010000 /* Assign SS for irq priority 1 */
+#define DEVCFG3_FSRSSEL_2       0x00020000 /* Assign SS for irq priority 2 */
+#define DEVCFG3_FSRSSEL_3       0x00030000 /* Assign SS for irq priority 3 */
+#define DEVCFG3_FSRSSEL_4       0x00040000 /* Assign SS for irq priority 4 */
+#define DEVCFG3_FSRSSEL_5       0x00050000 /* Assign SS for irq priority 5 */
+#define DEVCFG3_FSRSSEL_6       0x00060000 /* Assign SS for irq priority 6 */
+#define DEVCFG3_FSRSSEL_7       0x00070000 /* Assign SS for irq priority 7 */
+#define DEVCFG3_FMIIEN          0x01000000 /* Ethernet MII enable */
+#define DEVCFG3_FETHIO          0x02000000 /* Ethernet pins default */
+#define DEVCFG3_FCANIO          0x04000000 /* CAN pins default */
+#define DEVCFG3_FUSBIDIO        0x40000000 /* USBID pin: controlled by USB */
+#define DEVCFG3_FVBUSONIO       0x80000000 /* VBuson pin: controlled by USB */
+
+/*--------------------------------------
+ * Interrupt controller registers.
+ */
+#define INTCON          PIC32_R(0x81000)       /* Interrupt Control */
+#define INTCONCLR       PIC32_R(0x81004)
+#define INTCONSET       PIC32_R(0x81008)
+#define INTCONINV       PIC32_R(0x8100C)
+#define INTSTAT         PIC32_R(0x81010)       /* Interrupt Status */
+#define IPTMR           PIC32_R(0x81020)       /* Temporal Proximity Timer */
+#define IPTMRCLR        PIC32_R(0x81024)
+#define IPTMRSET        PIC32_R(0x81028)
+#define IPTMRINV        PIC32_R(0x8102C)
+/* IFS(0..2) - Interrupt Flag Status */
+#define IFS(n)          PIC32_R(0x81030+((n)<<4))
+#define IFSCLR(n)       PIC32_R(0x81034+((n)<<4))
+#define IFSSET(n)       PIC32_R(0x81038+((n)<<4))
+#define IFSINV(n)       PIC32_R(0x8103C+((n)<<4))
+#define IFS0            IFS(0)
+#define IFS1            IFS(1)
+#define IFS2            IFS(2)
+/* IEC(0..2) - Interrupt Enable Control */
+#define IEC(n)          PIC32_R(0x81060+((n)<<4))
+#define IECCLR(n)       PIC32_R(0x81064+((n)<<4))
+#define IECSET(n)       PIC32_R(0x81068+((n)<<4))
+#define IECINV(n)       PIC32_R(0x8106C+((n)<<4))
+#define IEC0            IEC(0)
+#define IEC1            IEC(1)
+#define IEC2            IEC(2)
+/* IPC(0..12) - Interrupt Priority Control */
+#define IPC(n)          PIC32_R(0x81090+((n)<<4))
+#define IPCCLR(n)       PIC32_R(0x81094+((n)<<4))
+#define IPCSET(n)       PIC32_R(0x81098+((n)<<4))
+#define IPCINV(n)       PIC32_R(0x8109C+((n)<<4))
+#define IPC0            IPC(0)
+#define IPC1            IPC(1)
+#define IPC2            IPC(2)
+#define IPC3            IPC(3)
+#define IPC4            IPC(4)
+#define IPC5            IPC(5)
+#define IPC6            IPC(6)
+#define IPC7            IPC(7)
+#define IPC8            IPC(8)
+#define IPC9            IPC(9)
+#define IPC10           IPC(10)
+#define IPC11           IPC(11)
+#define IPC12           IPC(12)
+
+/*
+ * Interrupt Control register.
+ */
+#define PIC32_INTCON_INT0EP     0x0001  /* Rising edge polarity for
+                                         * external interrupt 0 */
+#define PIC32_INTCON_INT1EP     0x0002  /* Rising edge polarity for int1 */
+#define PIC32_INTCON_INT2EP     0x0004  /* Rising edge polarity for int2 */
+#define PIC32_INTCON_INT3EP     0x0008  /* Rising edge polarity for int3 */
+#define PIC32_INTCON_INT4EP     0x0010  /* Rising edge polarity for int4 */
+#define PIC32_INTCON_TPC(x)     ((x)<<8) /* Temporal proximity group prio */
+#define PIC32_INTCON_MVEC       0x1000  /* Multi-vectored mode */
+#define PIC32_INTCON_FRZ        0x4000  /* Freeze in debug mode */
+#define PIC32_INTCON_SS0        0x8000  /* Single vector has
+                                         * a shadow register set */
+/*
+ * Interrupt Status register.
+ */
+#define PIC32_INTSTAT_VEC(s)    ((s) & 0xFF)    /* Interrupt vector */
+#define PIC32_INTSTAT_SRIPL(s)  ((s) >> 8 & 7)  /* Requested priority level */
+#define PIC32_INTSTAT_SRIPL_MASK 0x0700
+
+/*
+ * Interrupt Prority Control register.
+ */
+#define PIC32_IPC_IS0(x)        (x)             /* Interrupt 0 subpriority */
+#define PIC32_IPC_IP0(x)        ((x)<<2)        /* Interrupt 0 priority */
+#define PIC32_IPC_IS1(x)        ((x)<<8)        /* Interrupt 1 subpriority */
+#define PIC32_IPC_IP1(x)        ((x)<<10)       /* Interrupt 1 priority */
+#define PIC32_IPC_IS2(x)        ((x)<<16)       /* Interrupt 2 subpriority */
+#define PIC32_IPC_IP2(x)        ((x)<<18)       /* Interrupt 2 priority */
+#define PIC32_IPC_IS3(x)        ((x)<<24)       /* Interrupt 3 subpriority */
+#define PIC32_IPC_IP3(x)        ((x)<<26)       /* Interrupt 3 priority */
+
+/*
+ * IRQ numbers for PIC32MX3xx/4xx/5xx/6xx/7xx
+ */
+#define PIC32_IRQ_CT        0   /* Core Timer Interrupt */
+#define PIC32_IRQ_CS0       1   /* Core Software Interrupt 0 */
+#define PIC32_IRQ_CS1       2   /* Core Software Interrupt 1 */
+#define PIC32_IRQ_INT0      3   /* External Interrupt 0 */
+#define PIC32_IRQ_T1        4   /* Timer1 */
+#define PIC32_IRQ_IC1       5   /* Input Capture 1 */
+#define PIC32_IRQ_OC1       6   /* Output Compare 1 */
+#define PIC32_IRQ_INT1      7   /* External Interrupt 1 */
+#define PIC32_IRQ_T2        8   /* Timer2 */
+#define PIC32_IRQ_IC2       9   /* Input Capture 2 */
+#define PIC32_IRQ_OC2       10  /* Output Compare 2 */
+#define PIC32_IRQ_INT2      11  /* External Interrupt 2 */
+#define PIC32_IRQ_T3        12  /* Timer3 */
+#define PIC32_IRQ_IC3       13  /* Input Capture 3 */
+#define PIC32_IRQ_OC3       14  /* Output Compare 3 */
+#define PIC32_IRQ_INT3      15  /* External Interrupt 3 */
+#define PIC32_IRQ_T4        16  /* Timer4 */
+#define PIC32_IRQ_IC4       17  /* Input Capture 4 */
+#define PIC32_IRQ_OC4       18  /* Output Compare 4 */
+#define PIC32_IRQ_INT4      19  /* External Interrupt 4 */
+#define PIC32_IRQ_T5        20  /* Timer5 */
+#define PIC32_IRQ_IC5       21  /* Input Capture 5 */
+#define PIC32_IRQ_OC5       22  /* Output Compare 5 */
+#define PIC32_IRQ_SPI1E     23  /* SPI1 Fault */
+#define PIC32_IRQ_SPI1TX    24  /* SPI1 Transfer Done */
+#define PIC32_IRQ_SPI1RX    25  /* SPI1 Receive Done */
+
+#define PIC32_IRQ_SPI3E     26  /* SPI3 Fault */
+#define PIC32_IRQ_SPI3TX    27  /* SPI3 Transfer Done */
+#define PIC32_IRQ_SPI3RX    28  /* SPI3 Receive Done */
+#define PIC32_IRQ_U1E       26  /* UART1 Error */
+#define PIC32_IRQ_U1RX      27  /* UART1 Receiver */
+#define PIC32_IRQ_U1TX      28  /* UART1 Transmitter */
+#define PIC32_IRQ_I2C3B     26  /* I2C3 Bus Collision Event */
+#define PIC32_IRQ_I2C3S     27  /* I2C3 Slave Event */
+#define PIC32_IRQ_I2C3M     28  /* I2C3 Master Event */
+
+#define PIC32_IRQ_I2C1B     29  /* I2C1 Bus Collision Event */
+#define PIC32_IRQ_I2C1S     30  /* I2C1 Slave Event */
+#define PIC32_IRQ_I2C1M     31  /* I2C1 Master Event */
+#define PIC32_IRQ_CN        32  /* Input Change Interrupt */
+#define PIC32_IRQ_AD1       33  /* ADC1 Convert Done */
+#define PIC32_IRQ_PMP       34  /* Parallel Master Port */
+#define PIC32_IRQ_CMP1      35  /* Comparator Interrupt */
+#define PIC32_IRQ_CMP2      36  /* Comparator Interrupt */
+
+#define PIC32_IRQ_SPI2E     37  /* SPI2 Fault */
+#define PIC32_IRQ_SPI2TX    38  /* SPI2 Transfer Done */
+#define PIC32_IRQ_SPI2RX    39  /* SPI2 Receive Done */
+#define PIC32_IRQ_U3E       37  /* UART3 Error */
+#define PIC32_IRQ_U3RX      38  /* UART3 Receiver */
+#define PIC32_IRQ_U3TX      39  /* UART3 Transmitter */
+#define PIC32_IRQ_I2C4B     37  /* I2C4 Bus Collision Event */
+#define PIC32_IRQ_I2C4S     38  /* I2C4 Slave Event */
+#define PIC32_IRQ_I2C4M     39  /* I2C4 Master Event */
+
+#define PIC32_IRQ_SPI4E     40  /* SPI4 Fault */
+#define PIC32_IRQ_SPI4TX    41  /* SPI4 Transfer Done */
+#define PIC32_IRQ_SPI4RX    42  /* SPI4 Receive Done */
+#define PIC32_IRQ_U2E       40  /* UART2 Error */
+#define PIC32_IRQ_U2RX      41  /* UART2 Receiver */
+#define PIC32_IRQ_U2TX      42  /* UART2 Transmitter */
+#define PIC32_IRQ_I2C5B     40  /* I2C5 Bus Collision Event */
+#define PIC32_IRQ_I2C5S     41  /* I2C5 Slave Event */
+#define PIC32_IRQ_I2C5M     42  /* I2C5 Master Event */
+
+#define PIC32_IRQ_I2C2B     43  /* I2C2 Bus Collision Event */
+#define PIC32_IRQ_I2C2S     44  /* I2C2 Slave Event */
+#define PIC32_IRQ_I2C2M     45  /* I2C2 Master Event */
+#define PIC32_IRQ_FSCM      46  /* Fail-Safe Clock Monitor */
+#define PIC32_IRQ_RTCC      47  /* Real-Time Clock and Calendar */
+#define PIC32_IRQ_DMA0      48  /* DMA Channel 0 */
+#define PIC32_IRQ_DMA1      49  /* DMA Channel 1 */
+#define PIC32_IRQ_DMA2      50  /* DMA Channel 2 */
+#define PIC32_IRQ_DMA3      51  /* DMA Channel 3 */
+#define PIC32_IRQ_DMA4      52  /* DMA Channel 4 */
+#define PIC32_IRQ_DMA5      53  /* DMA Channel 5 */
+#define PIC32_IRQ_DMA6      54  /* DMA Channel 6 */
+#define PIC32_IRQ_DMA7      55  /* DMA Channel 7 */
+#define PIC32_IRQ_FCE       56  /* Flash Control Event */
+#define PIC32_IRQ_USB       57  /* USB */
+#define PIC32_IRQ_CAN1      58  /* Control Area Network 1 */
+#define PIC32_IRQ_CAN2      59  /* Control Area Network 2 */
+#define PIC32_IRQ_ETH       60  /* Ethernet Interrupt */
+#define PIC32_IRQ_IC1E      61  /* Input Capture 1 Error */
+#define PIC32_IRQ_IC2E      62  /* Input Capture 2 Error */
+#define PIC32_IRQ_IC3E      63  /* Input Capture 3 Error */
+#define PIC32_IRQ_IC4E      64  /* Input Capture 4 Error */
+#define PIC32_IRQ_IC5E      65  /* Input Capture 5 Error */
+#define PIC32_IRQ_PMPE      66  /* Parallel Master Port Error */
+#define PIC32_IRQ_U4E       67  /* UART4 Error */
+#define PIC32_IRQ_U4RX      68  /* UART4 Receiver */
+#define PIC32_IRQ_U4TX      69  /* UART4 Transmitter */
+#define PIC32_IRQ_U6E       70  /* UART6 Error */
+#define PIC32_IRQ_U6RX      71  /* UART6 Receiver */
+#define PIC32_IRQ_U6TX      72  /* UART6 Transmitter */
+#define PIC32_IRQ_U5E       73  /* UART5 Error */
+#define PIC32_IRQ_U5RX      74  /* UART5 Receiver */
+#define PIC32_IRQ_U5TX      75  /* UART5 Transmitter */
+
+/*
+ * Interrupt vector numbers for PIC32MX3xx/4xx/5xx/6xx/7xx
+ */
+#define PIC32_VECT_CT       0   /* Core Timer Interrupt */
+#define PIC32_VECT_CS0      1   /* Core Software Interrupt 0 */
+#define PIC32_VECT_CS1      2   /* Core Software Interrupt 1 */
+#define PIC32_VECT_INT0     3   /* External Interrupt 0 */
+#define PIC32_VECT_T1       4   /* Timer1 */
+#define PIC32_VECT_IC1      5   /* Input Capture 1 */
+#define PIC32_VECT_OC1      6   /* Output Compare 1 */
+#define PIC32_VECT_INT1     7   /* External Interrupt 1 */
+#define PIC32_VECT_T2       8   /* Timer2 */
+#define PIC32_VECT_IC2      9   /* Input Capture 2 */
+#define PIC32_VECT_OC2      10  /* Output Compare 2 */
+#define PIC32_VECT_INT2     11  /* External Interrupt 2 */
+#define PIC32_VECT_T3       12  /* Timer3 */
+#define PIC32_VECT_IC3      13  /* Input Capture 3 */
+#define PIC32_VECT_OC3      14  /* Output Compare 3 */
+#define PIC32_VECT_INT3     15  /* External Interrupt 3 */
+#define PIC32_VECT_T4       16  /* Timer4 */
+#define PIC32_VECT_IC4      17  /* Input Capture 4 */
+#define PIC32_VECT_OC4      18  /* Output Compare 4 */
+#define PIC32_VECT_INT4     19  /* External Interrupt 4 */
+#define PIC32_VECT_T5       20  /* Timer5 */
+#define PIC32_VECT_IC5      21  /* Input Capture 5 */
+#define PIC32_VECT_OC5      22  /* Output Compare 5 */
+#define PIC32_VECT_SPI1     23  /* SPI1 */
+
+#define PIC32_VECT_SPI3     24  /* SPI3 */
+#define PIC32_VECT_U1       24  /* UART1 */
+#define PIC32_VECT_I2C3     24  /* I2C3 */
+
+#define PIC32_VECT_I2C1     25  /* I2C1 */
+#define PIC32_VECT_CN       26  /* Input Change Interrupt */
+#define PIC32_VECT_AD1      27  /* ADC1 Convert Done */
+#define PIC32_VECT_PMP      28  /* Parallel Master Port */
+#define PIC32_VECT_CMP1     29  /* Comparator Interrupt */
+#define PIC32_VECT_CMP2     30  /* Comparator Interrupt */
+
+#define PIC32_VECT_SPI2     31  /* SPI2 */
+#define PIC32_VECT_U3       31  /* UART3 */
+#define PIC32_VECT_I2C4     31  /* I2C4 */
+
+#define PIC32_VECT_SPI4     32  /* SPI4 */
+#define PIC32_VECT_U2       32  /* UART2 */
+#define PIC32_VECT_I2C5     32  /* I2C5 */
+
+#define PIC32_VECT_I2C2     33  /* I2C2 */
+#define PIC32_VECT_FSCM     34  /* Fail-Safe Clock Monitor */
+#define PIC32_VECT_RTCC     35  /* Real-Time Clock and Calendar */
+#define PIC32_VECT_DMA0     36  /* DMA Channel 0 */
+#define PIC32_VECT_DMA1     37  /* DMA Channel 1 */
+#define PIC32_VECT_DMA2     38  /* DMA Channel 2 */
+#define PIC32_VECT_DMA3     39  /* DMA Channel 3 */
+#define PIC32_VECT_DMA4     40  /* DMA Channel 4 */
+#define PIC32_VECT_DMA5     41  /* DMA Channel 5 */
+#define PIC32_VECT_DMA6     42  /* DMA Channel 6 */
+#define PIC32_VECT_DMA7     43  /* DMA Channel 7 */
+#define PIC32_VECT_FCE      44  /* Flash Control Event */
+#define PIC32_VECT_USB      45  /* USB */
+#define PIC32_VECT_CAN1     46  /* Control Area Network 1 */
+#define PIC32_VECT_CAN2     47  /* Control Area Network 2 */
+#define PIC32_VECT_ETH      48  /* Ethernet Interrupt */
+#define PIC32_VECT_U4       49  /* UART4 */
+#define PIC32_VECT_U6       50  /* UART6 */
+#define PIC32_VECT_U5       51  /* UART5 */
+
+#endif /* _IO_PIC32MX_H */
diff --git a/hw/mips/pic32mz.h b/hw/mips/pic32mz.h
new file mode 100644
index 0000000..1aa7dac
--- /dev/null
+++ b/hw/mips/pic32mz.h
@@ -0,0 +1,2093 @@ 
+/*
+ * Hardware register defines for Microchip PIC32MZ microcontroller.
+ *
+ * Copyright (C) 2013 Serge Vakulenko
+ *
+ * Permission to use, copy, modify, and distribute this software
+ * and its documentation for any purpose and without fee is hereby
+ * granted, provided that the above copyright notice appear in all
+ * copies and that both that the copyright notice and this
+ * permission notice and warranty disclaimer appear in supporting
+ * documentation, and that the name of the author not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ *
+ * The author disclaim all warranties with regard to this
+ * software, including all implied warranties of merchantability
+ * and fitness.  In no event shall the author be liable for any
+ * special, indirect or consequential damages or any damages
+ * whatsoever resulting from loss of use, data or profits, whether
+ * in an action of contract, negligence or other tortious action,
+ * arising out of or in connection with the use or performance of
+ * this software.
+ */
+#ifndef _IO_PIC32MZ_H
+#define _IO_PIC32MZ_H
+
+/*
+ * Register memory map:
+ *
+ *  BF80 0000...03FF    Configuration
+ *  BF80 0600...07FF    Flash Controller
+ *  BF80 0800...09FF    Watchdog Timer
+ *  BF80 0A00...0BFF    Deadman Timer
+ *  BF80 0C00...0DFF    RTCC
+ *  BF80 0E00...0FFF    CVref
+ *  BF80 1200...13FF    Oscillator
+ *  BF80 1400...17FF    PPS
+ *
+ *  BF81 0000...0FFF    Interrupt Controller
+ *  BF81 1000...1FFF    DMA
+ *
+ *  BF82 0000...09FF    I2C1 - I2C5
+ *  BF82 1000...1BFF    SPI1 - SPI6
+ *  BF82 2000...2BFF    UART1 - UART6
+ *  BF82 E000...E1FF    PMP
+ *
+ *  BF84 0000...11FF    Timer1 - Timer9
+ *  BF84 2000...31FF    IC1 - IC9
+ *  BF84 4000...51FF    OC1 - OC9
+ *  BF84 B000...B3FF    ADC1
+ *  BF84 C000...C1FF    Comparator 1, 2
+ *
+ *  BF86 0000...09FF    PORTA - PORTK
+ *
+ *  BF88 0000...1FFF    CAN1 and CAN2
+ *  BF88 2000...2FFF    Ethernet
+ *
+ *  BF8E 0000...0FFF    Prefetch
+ *  BF8E 1000...1FFF    EBI
+ *  BF8E 2000...2FFF    SQI1
+ *  BF8E 3000...3FFF    USB
+ *  BF8E 5000...5FFF    Crypto
+ *  BF8E 6000...6FFF    RNG
+ *
+ *  BF8F 0000...FFFF    System Bus
+ */
+
+/*--------------------------------------
+ * Configuration registers.
+ */
+#define DEVCFG0         0x9fc0fffc
+#define DEVCFG1         0x9fc0fff8
+#define DEVCFG2         0x9fc0fff4
+#define DEVCFG3         0x9fc0fff0
+
+/*
+ * Config0 register at 1fc0ffcc, inverted.
+ */
+#define DEVCFG0_DEBUG_ENABLE    0x00000002 /* Enable background debugger */
+#define DEVCFG0_JTAG_DISABLE    0x00000004 /* Disable JTAG port */
+#define DEVCFG0_ICESEL_PGE2     0x00000008 /* Use PGC2/PGD2
+                                            * (default PGC1/PGD1) */
+#define DEVCFG0_TRC_DISABLE     0x00000020 /* Disable Trace port */
+#define DEVCFG0_MICROMIPS       0x00000040 /* Boot in microMIPS mode */
+#define DEVCFG0_ECC_MASK        0x00000300 /* Flash ECC mode mask */
+#define DEVCFG0_ECC_ENABLE      0x00000300 /* Enable Flash ECC */
+#define DEVCFG0_DECC_ENABLE     0x00000200 /* Enable Dynamic Flash ECC */
+#define DEVCFG0_ECC_DIS_LOCK    0x00000100 /* Disable ECC, lock ECCCON */
+#define DEVCFG0_FSLEEP          0x00000400 /* Flash power down controlled
+                                            * by VREGS bit */
+#define DEVCFG0_DBGPER0         0x00001000 /* In Debug mode, deny CPU access to
+                                            * Permission Group 0 regions */
+#define DEVCFG0_DBGPER1         0x00002000 /* In Debug mode, deny CPU access to
+                                            * Permission Group 1 regions */
+#define DEVCFG0_DBGPER2         0x00004000 /* In Debug mode, deny CPU access to
+                                            * Permission Group 2 regions */
+#define DEVCFG0_EJTAG_REDUCED   0x40000000 /* Reduced EJTAG functionality */
+
+/*
+ * Config1 register at 1fc0ffc8.
+ */
+#define DEVCFG1_UNUSED          0x00003800
+#define DEVCFG1_FNOSC_MASK      0x00000007 /* Oscillator selection */
+#define DEVCFG1_FNOSC_SPLL      0x00000001 /* SPLL */
+#define DEVCFG1_FNOSC_POSC      0x00000002 /* Primary oscillator XT, HS, EC */
+#define DEVCFG1_FNOSC_SOSC      0x00000004 /* Secondary oscillator */
+#define DEVCFG1_FNOSC_LPRC      0x00000005 /* Low-power RC */
+#define DEVCFG1_FNOSC_FRCDIV    0x00000007 /* Fast RC with divide-by-N */
+#define DEVCFG1_DMTINV_MASK     0x00000038 /* Deadman Timer Count
+                                            * Window Interval */
+#define DEVCFG1_DMTINV_1_2      0x00000008 /* 1/2 of counter value */
+#define DEVCFG1_DMTINV_3_4      0x00000010 /* 3/4 of counter value */
+#define DEVCFG1_DMTINV_7_8      0x00000018 /* 7/8 of counter value */
+#define DEVCFG1_DMTINV_15_16    0x00000020 /* 15/16 of counter value */
+#define DEVCFG1_DMTINV_31_32    0x00000028 /* 31/32 of counter value */
+#define DEVCFG1_DMTINV_63_64    0x00000030 /* 63/64 of counter value */
+#define DEVCFG1_DMTINV_127_128  0x00000038 /* 127/128 of counter value */
+#define DEVCFG1_FSOSCEN         0x00000040 /* Secondary oscillator enable */
+#define DEVCFG1_IESO            0x00000080 /* Internal-external switch over */
+#define DEVCFG1_POSCMOD_MASK    0x00000300 /* Primary oscillator config */
+#define DEVCFG1_POSCMOD_EXT     0x00000000 /* External mode */
+#define DEVCFG1_POSCMOD_HS      0x00000200 /* HS oscillator */
+#define DEVCFG1_POSCMOD_DISABLE 0x00000300 /* Disabled */
+#define DEVCFG1_CLKO_DISABLE    0x00000400 /* Disable CLKO output */
+#define DEVCFG1_FCKS_ENABLE     0x00004000 /* Enable clock switching */
+#define DEVCFG1_FCKM_ENABLE     0x00008000 /* Enable fail-safe clk monitoring */
+#define DEVCFG1_WDTPS_MASK      0x001f0000 /* Watchdog postscale */
+#define DEVCFG1_WDTPS_1         0x00000000 /* 1:1 */
+#define DEVCFG1_WDTPS_2         0x00010000 /* 1:2 */
+#define DEVCFG1_WDTPS_4         0x00020000 /* 1:4 */
+#define DEVCFG1_WDTPS_8         0x00030000 /* 1:8 */
+#define DEVCFG1_WDTPS_16        0x00040000 /* 1:16 */
+#define DEVCFG1_WDTPS_32        0x00050000 /* 1:32 */
+#define DEVCFG1_WDTPS_64        0x00060000 /* 1:64 */
+#define DEVCFG1_WDTPS_128       0x00070000 /* 1:128 */
+#define DEVCFG1_WDTPS_256       0x00080000 /* 1:256 */
+#define DEVCFG1_WDTPS_512       0x00090000 /* 1:512 */
+#define DEVCFG1_WDTPS_1024      0x000a0000 /* 1:1024 */
+#define DEVCFG1_WDTPS_2048      0x000b0000 /* 1:2048 */
+#define DEVCFG1_WDTPS_4096      0x000c0000 /* 1:4096 */
+#define DEVCFG1_WDTPS_8192      0x000d0000 /* 1:8192 */
+#define DEVCFG1_WDTPS_16384     0x000e0000 /* 1:16384 */
+#define DEVCFG1_WDTPS_32768     0x000f0000 /* 1:32768 */
+#define DEVCFG1_WDTPS_65536     0x00100000 /* 1:65536 */
+#define DEVCFG1_WDTPS_131072    0x00110000 /* 1:131072 */
+#define DEVCFG1_WDTPS_262144    0x00120000 /* 1:262144 */
+#define DEVCFG1_WDTPS_524288    0x00130000 /* 1:524288 */
+#define DEVCFG1_WDTPS_1048576   0x00140000 /* 1:1048576 */
+#define DEVCFG1_WDTSPGM         0x00200000 /* Watchdog stops during
+                                            * Flash programming */
+#define DEVCFG1_WINDIS          0x00400000 /* Watchdog is in non-Window mode */
+#define DEVCFG1_FWDTEN          0x00800000 /* Watchdog enable */
+#define DEVCFG1_FWDTWINSZ_75    0x00000000 /* Watchdog window size is 75% */
+#define DEVCFG1_FWDTWINSZ_50    0x01000000 /* 50% */
+#define DEVCFG1_FWDTWINSZ_375   0x02000000 /* 37.5% */
+#define DEVCFG1_FWDTWINSZ_25    0x03000000 /* 25% */
+#define DEVCFG1_DMTCNT(n)       ((n)<<26)  /* Deadman Timer Count Select */
+#define DEVCFG1_FDMTEN          0x80000000 /* Deadman Timer enable */
+
+/*
+ * Config2 register at 1fc0ffc4.
+ */
+#define DEVCFG2_UNUSED          0x3ff88008
+#define DEVCFG2_FPLLIDIV_MASK   0x00000007 /* PLL input divider */
+#define DEVCFG2_FPLLIDIV_1      0x00000000 /* 1x */
+#define DEVCFG2_FPLLIDIV_2      0x00000001 /* 2x */
+#define DEVCFG2_FPLLIDIV_3      0x00000002 /* 3x */
+#define DEVCFG2_FPLLIDIV_4      0x00000003 /* 4x */
+#define DEVCFG2_FPLLIDIV_5      0x00000004 /* 5x */
+#define DEVCFG2_FPLLIDIV_6      0x00000005 /* 6x */
+#define DEVCFG2_FPLLIDIV_7      0x00000006 /* 7x */
+#define DEVCFG2_FPLLIDIV_8      0x00000007 /* 8x */
+#define DEVCFG2_FPLLRNG_MASK    0x00000070 /* PLL input frequency range */
+#define DEVCFG2_FPLLRNG_BYPASS  0x00000000 /* Bypass */
+#define DEVCFG2_FPLLRNG_5_10    0x00000010 /* 5-10 MHz */
+#define DEVCFG2_FPLLRNG_8_16    0x00000020 /* 8-16 MHz */
+#define DEVCFG2_FPLLRNG_13_26   0x00000030 /* 13-26 MHz */
+#define DEVCFG2_FPLLRNG_21_42   0x00000040 /* 21-42 MHz */
+#define DEVCFG2_FPLLRNG_34_64   0x00000050 /* 34-64 MHz */
+#define DEVCFG2_FPLLICLK_FRC    0x00000080 /* Select FRC as input to PLL */
+#define DEVCFG2_FPLLMULT(n)     (((n)-1)<<8) /* PLL Feedback Divider */
+#define DEVCFG2_FPLLODIV_MASK   0x00070000 /* Default PLL output divisor */
+#define DEVCFG2_FPLLODIV_2      0x00000000 /* 2x */
+#define DEVCFG2_FPLLODIV_4      0x00020000 /* 4x */
+#define DEVCFG2_FPLLODIV_8      0x00030000 /* 8x */
+#define DEVCFG2_FPLLODIV_16     0x00040000 /* 16x */
+#define DEVCFG2_FPLLODIV_32     0x00050000 /* 32x */
+#define DEVCFG2_UPLLFSEL_24     0x40000000 /* USB PLL input clock is 24 MHz
+                                            * (default 12 MHz) */
+#define DEVCFG2_UPLLEN          0x80000000 /* Enable USB PLL */
+
+/*
+ * Config3 register at 1fc0ffc0.
+ */
+#define DEVCFG3_UNUSED          0x84ff0000
+#define DEVCFG3_USERID_MASK     0x0000ffff /* User-defined ID */
+#define DEVCFG3_USERID(x)       ((x) & 0xffff)
+#define DEVCFG3_FMIIEN          0x01000000 /* Ethernet MII enable */
+#define DEVCFG3_FETHIO          0x02000000 /* Default Ethernet pins */
+#define DEVCFG3_PGL1WAY         0x08000000 /* Permission Group Lock -
+                                            * only 1 reconfig */
+#define DEVCFG3_PMDL1WAY        0x10000000 /* Peripheral Module Disable -
+                                            * only 1 reconfig */
+#define DEVCFG3_IOL1WAY         0x20000000 /* Peripheral Pin Select -
+                                            * only 1 reconfig */
+#define DEVCFG3_FUSBIDIO        0x40000000 /* USBID pin: controlled by USB */
+
+/*--------------------------------------
+ * Peripheral registers.
+ */
+#define PIC32_R(a)              (a)
+
+/*--------------------------------------
+ * Port A-K registers.
+ */
+#define ANSELA          PIC32_R(0x60000) /* Port A: analog select */
+#define ANSELACLR       PIC32_R(0x60004)
+#define ANSELASET       PIC32_R(0x60008)
+#define ANSELAINV       PIC32_R(0x6000C)
+#define TRISA           PIC32_R(0x60010) /* A: mask of inputs */
+#define TRISACLR        PIC32_R(0x60014)
+#define TRISASET        PIC32_R(0x60018)
+#define TRISAINV        PIC32_R(0x6001C)
+#define PORTA           PIC32_R(0x60020) /* A: read inputs, write outputs */
+#define PORTACLR        PIC32_R(0x60024)
+#define PORTASET        PIC32_R(0x60028)
+#define PORTAINV        PIC32_R(0x6002C)
+#define LATA            PIC32_R(0x60030) /* A: read/write outputs */
+#define LATACLR         PIC32_R(0x60034)
+#define LATASET         PIC32_R(0x60038)
+#define LATAINV         PIC32_R(0x6003C)
+#define ODCA            PIC32_R(0x60040) /* A: open drain configuration */
+#define ODCACLR         PIC32_R(0x60044)
+#define ODCASET         PIC32_R(0x60048)
+#define ODCAINV         PIC32_R(0x6004C)
+#define CNPUA           PIC32_R(0x60050) /* A: input pin pull-up enable */
+#define CNPUACLR        PIC32_R(0x60054)
+#define CNPUASET        PIC32_R(0x60058)
+#define CNPUAINV        PIC32_R(0x6005C)
+#define CNPDA           PIC32_R(0x60060) /* A: input pin pull-down enable */
+#define CNPDACLR        PIC32_R(0x60064)
+#define CNPDASET        PIC32_R(0x60068)
+#define CNPDAINV        PIC32_R(0x6006C)
+#define CNCONA          PIC32_R(0x60070) /* A: interrupt-on-change control */
+#define CNCONACLR       PIC32_R(0x60074)
+#define CNCONASET       PIC32_R(0x60078)
+#define CNCONAINV       PIC32_R(0x6007C)
+#define CNENA           PIC32_R(0x60080) /* A: input change interrupt enable */
+#define CNENACLR        PIC32_R(0x60084)
+#define CNENASET        PIC32_R(0x60088)
+#define CNENAINV        PIC32_R(0x6008C)
+#define CNSTATA         PIC32_R(0x60090) /* A: status */
+#define CNSTATACLR      PIC32_R(0x60094)
+#define CNSTATASET      PIC32_R(0x60098)
+#define CNSTATAINV      PIC32_R(0x6009C)
+
+#define ANSELB          PIC32_R(0x60100) /* Port B: analog select */
+#define ANSELBCLR       PIC32_R(0x60104)
+#define ANSELBSET       PIC32_R(0x60108)
+#define ANSELBINV       PIC32_R(0x6010C)
+#define TRISB           PIC32_R(0x60110) /* B: mask of inputs */
+#define TRISBCLR        PIC32_R(0x60114)
+#define TRISBSET        PIC32_R(0x60118)
+#define TRISBINV        PIC32_R(0x6011C)
+#define PORTB           PIC32_R(0x60120) /* B: read inputs, write outputs */
+#define PORTBCLR        PIC32_R(0x60124)
+#define PORTBSET        PIC32_R(0x60128)
+#define PORTBINV        PIC32_R(0x6012C)
+#define LATB            PIC32_R(0x60130) /* B: read/write outputs */
+#define LATBCLR         PIC32_R(0x60134)
+#define LATBSET         PIC32_R(0x60138)
+#define LATBINV         PIC32_R(0x6013C)
+#define ODCB            PIC32_R(0x60140) /* B: open drain configuration */
+#define ODCBCLR         PIC32_R(0x60144)
+#define ODCBSET         PIC32_R(0x60148)
+#define ODCBINV         PIC32_R(0x6014C)
+#define CNPUB           PIC32_R(0x60150) /* B: input pin pull-up enable */
+#define CNPUBCLR        PIC32_R(0x60154)
+#define CNPUBSET        PIC32_R(0x60158)
+#define CNPUBINV        PIC32_R(0x6015C)
+#define CNPDB           PIC32_R(0x60160) /* B: input pin pull-down enable */
+#define CNPDBCLR        PIC32_R(0x60164)
+#define CNPDBSET        PIC32_R(0x60168)
+#define CNPDBINV        PIC32_R(0x6016C)
+#define CNCONB          PIC32_R(0x60170) /* B: interrupt-on-change control */
+#define CNCONBCLR       PIC32_R(0x60174)
+#define CNCONBSET       PIC32_R(0x60178)
+#define CNCONBINV       PIC32_R(0x6017C)
+#define CNENB           PIC32_R(0x60180) /* B: input change interrupt enable */
+#define CNENBCLR        PIC32_R(0x60184)
+#define CNENBSET        PIC32_R(0x60188)
+#define CNENBINV        PIC32_R(0x6018C)
+#define CNSTATB         PIC32_R(0x60190) /* B: status */
+#define CNSTATBCLR      PIC32_R(0x60194)
+#define CNSTATBSET      PIC32_R(0x60198)
+#define CNSTATBINV      PIC32_R(0x6019C)
+
+#define ANSELC          PIC32_R(0x60200) /* Port C: analog select */
+#define ANSELCCLR       PIC32_R(0x60204)
+#define ANSELCSET       PIC32_R(0x60208)
+#define ANSELCINV       PIC32_R(0x6020C)
+#define TRISC           PIC32_R(0x60210) /* C: mask of inputs */
+#define TRISCCLR        PIC32_R(0x60214)
+#define TRISCSET        PIC32_R(0x60218)
+#define TRISCINV        PIC32_R(0x6021C)
+#define PORTC           PIC32_R(0x60220) /* C: read inputs, write outputs */
+#define PORTCCLR        PIC32_R(0x60224)
+#define PORTCSET        PIC32_R(0x60228)
+#define PORTCINV        PIC32_R(0x6022C)
+#define LATC            PIC32_R(0x60230) /* C: read/write outputs */
+#define LATCCLR         PIC32_R(0x60234)
+#define LATCSET         PIC32_R(0x60238)
+#define LATCINV         PIC32_R(0x6023C)
+#define ODCC            PIC32_R(0x60240) /* C: open drain configuration */
+#define ODCCCLR         PIC32_R(0x60244)
+#define ODCCSET         PIC32_R(0x60248)
+#define ODCCINV         PIC32_R(0x6024C)
+#define CNPUC           PIC32_R(0x60250) /* C: input pin pull-up enable */
+#define CNPUCCLR        PIC32_R(0x60254)
+#define CNPUCSET        PIC32_R(0x60258)
+#define CNPUCINV        PIC32_R(0x6025C)
+#define CNPDC           PIC32_R(0x60260) /* C: input pin pull-down enable */
+#define CNPDCCLR        PIC32_R(0x60264)
+#define CNPDCSET        PIC32_R(0x60268)
+#define CNPDCINV        PIC32_R(0x6026C)
+#define CNCONC          PIC32_R(0x60270) /* C: interrupt-on-change control */
+#define CNCONCCLR       PIC32_R(0x60274)
+#define CNCONCSET       PIC32_R(0x60278)
+#define CNCONCINV       PIC32_R(0x6027C)
+#define CNENC           PIC32_R(0x60280) /* C: input change interrupt enable */
+#define CNENCCLR        PIC32_R(0x60284)
+#define CNENCSET        PIC32_R(0x60288)
+#define CNENCINV        PIC32_R(0x6028C)
+#define CNSTATC         PIC32_R(0x60290) /* C: status */
+#define CNSTATCCLR      PIC32_R(0x60294)
+#define CNSTATCSET      PIC32_R(0x60298)
+#define CNSTATCINV      PIC32_R(0x6029C)
+
+#define ANSELD          PIC32_R(0x60300) /* Port D: analog select */
+#define ANSELDCLR       PIC32_R(0x60304)
+#define ANSELDSET       PIC32_R(0x60308)
+#define ANSELDINV       PIC32_R(0x6030C)
+#define TRISD           PIC32_R(0x60310) /* D: mask of inputs */
+#define TRISDCLR        PIC32_R(0x60314)
+#define TRISDSET        PIC32_R(0x60318)
+#define TRISDINV        PIC32_R(0x6031C)
+#define PORTD           PIC32_R(0x60320) /* D: read inputs, write outputs */
+#define PORTDCLR        PIC32_R(0x60324)
+#define PORTDSET        PIC32_R(0x60328)
+#define PORTDINV        PIC32_R(0x6032C)
+#define LATD            PIC32_R(0x60330) /* D: read/write outputs */
+#define LATDCLR         PIC32_R(0x60334)
+#define LATDSET         PIC32_R(0x60338)
+#define LATDINV         PIC32_R(0x6033C)
+#define ODCD            PIC32_R(0x60340) /* D: open drain configuration */
+#define ODCDCLR         PIC32_R(0x60344)
+#define ODCDSET         PIC32_R(0x60348)
+#define ODCDINV         PIC32_R(0x6034C)
+#define CNPUD           PIC32_R(0x60350) /* D: input pin pull-up enable */
+#define CNPUDCLR        PIC32_R(0x60354)
+#define CNPUDSET        PIC32_R(0x60358)
+#define CNPUDINV        PIC32_R(0x6035C)
+#define CNPDD           PIC32_R(0x60360) /* D: input pin pull-down enable */
+#define CNPDDCLR        PIC32_R(0x60364)
+#define CNPDDSET        PIC32_R(0x60368)
+#define CNPDDINV        PIC32_R(0x6036C)
+#define CNCOND          PIC32_R(0x60370) /* D: interrupt-on-change control */
+#define CNCONDCLR       PIC32_R(0x60374)
+#define CNCONDSET       PIC32_R(0x60378)
+#define CNCONDINV       PIC32_R(0x6037C)
+#define CNEND           PIC32_R(0x60380) /* D: input change interrupt enable */
+#define CNENDCLR        PIC32_R(0x60384)
+#define CNENDSET        PIC32_R(0x60388)
+#define CNENDINV        PIC32_R(0x6038C)
+#define CNSTATD         PIC32_R(0x60390) /* D: status */
+#define CNSTATDCLR      PIC32_R(0x60394)
+#define CNSTATDSET      PIC32_R(0x60398)
+#define CNSTATDINV      PIC32_R(0x6039C)
+
+#define ANSELE          PIC32_R(0x60400) /* Port E: analog select */
+#define ANSELECLR       PIC32_R(0x60404)
+#define ANSELESET       PIC32_R(0x60408)
+#define ANSELEINV       PIC32_R(0x6040C)
+#define TRISE           PIC32_R(0x60410) /* E: mask of inputs */
+#define TRISECLR        PIC32_R(0x60414)
+#define TRISESET        PIC32_R(0x60418)
+#define TRISEINV        PIC32_R(0x6041C)
+#define PORTE           PIC32_R(0x60420) /* E: read inputs, write outputs */
+#define PORTECLR        PIC32_R(0x60424)
+#define PORTESET        PIC32_R(0x60428)
+#define PORTEINV        PIC32_R(0x6042C)
+#define LATE            PIC32_R(0x60430) /* E: read/write outputs */
+#define LATECLR         PIC32_R(0x60434)
+#define LATESET         PIC32_R(0x60438)
+#define LATEINV         PIC32_R(0x6043C)
+#define ODCE            PIC32_R(0x60440) /* E: open drain configuration */
+#define ODCECLR         PIC32_R(0x60444)
+#define ODCESET         PIC32_R(0x60448)
+#define ODCEINV         PIC32_R(0x6044C)
+#define CNPUE           PIC32_R(0x60450) /* E: input pin pull-up enable */
+#define CNPUECLR        PIC32_R(0x60454)
+#define CNPUESET        PIC32_R(0x60458)
+#define CNPUEINV        PIC32_R(0x6045C)
+#define CNPDE           PIC32_R(0x60460) /* E: input pin pull-down enable */
+#define CNPDECLR        PIC32_R(0x60464)
+#define CNPDESET        PIC32_R(0x60468)
+#define CNPDEINV        PIC32_R(0x6046C)
+#define CNCONE          PIC32_R(0x60470) /* E: interrupt-on-change control */
+#define CNCONECLR       PIC32_R(0x60474)
+#define CNCONESET       PIC32_R(0x60478)
+#define CNCONEINV       PIC32_R(0x6047C)
+#define CNENE           PIC32_R(0x60480) /* E: input change interrupt enable */
+#define CNENECLR        PIC32_R(0x60484)
+#define CNENESET        PIC32_R(0x60488)
+#define CNENEINV        PIC32_R(0x6048C)
+#define CNSTATE         PIC32_R(0x60490) /* E: status */
+#define CNSTATECLR      PIC32_R(0x60494)
+#define CNSTATESET      PIC32_R(0x60498)
+#define CNSTATEINV      PIC32_R(0x6049C)
+
+#define ANSELF          PIC32_R(0x60500) /* Port F: analog select */
+#define ANSELFCLR       PIC32_R(0x60504)
+#define ANSELFSET       PIC32_R(0x60508)
+#define ANSELFINV       PIC32_R(0x6050C)
+#define TRISF           PIC32_R(0x60510) /* F: mask of inputs */
+#define TRISFCLR        PIC32_R(0x60514)
+#define TRISFSET        PIC32_R(0x60518)
+#define TRISFINV        PIC32_R(0x6051C)
+#define PORTF           PIC32_R(0x60520) /* F: read inputs, write outputs */
+#define PORTFCLR        PIC32_R(0x60524)
+#define PORTFSET        PIC32_R(0x60528)
+#define PORTFINV        PIC32_R(0x6052C)
+#define LATF            PIC32_R(0x60530) /* F: read/write outputs */
+#define LATFCLR         PIC32_R(0x60534)
+#define LATFSET         PIC32_R(0x60538)
+#define LATFINV         PIC32_R(0x6053C)
+#define ODCF            PIC32_R(0x60540) /* F: open drain configuration */
+#define ODCFCLR         PIC32_R(0x60544)
+#define ODCFSET         PIC32_R(0x60548)
+#define ODCFINV         PIC32_R(0x6054C)
+#define CNPUF           PIC32_R(0x60550) /* F: input pin pull-up enable */
+#define CNPUFCLR        PIC32_R(0x60554)
+#define CNPUFSET        PIC32_R(0x60558)
+#define CNPUFINV        PIC32_R(0x6055C)
+#define CNPDF           PIC32_R(0x60560) /* F: input pin pull-down enable */
+#define CNPDFCLR        PIC32_R(0x60564)
+#define CNPDFSET        PIC32_R(0x60568)
+#define CNPDFINV        PIC32_R(0x6056C)
+#define CNCONF          PIC32_R(0x60570) /* F: interrupt-on-change control */
+#define CNCONFCLR       PIC32_R(0x60574)
+#define CNCONFSET       PIC32_R(0x60578)
+#define CNCONFINV       PIC32_R(0x6057C)
+#define CNENF           PIC32_R(0x60580) /* F: input change interrupt enable */
+#define CNENFCLR        PIC32_R(0x60584)
+#define CNENFSET        PIC32_R(0x60588)
+#define CNENFINV        PIC32_R(0x6058C)
+#define CNSTATF         PIC32_R(0x60590) /* F: status */
+#define CNSTATFCLR      PIC32_R(0x60594)
+#define CNSTATFSET      PIC32_R(0x60598)
+#define CNSTATFINV      PIC32_R(0x6059C)
+
+#define ANSELG          PIC32_R(0x60600) /* Port G: analog select */
+#define ANSELGCLR       PIC32_R(0x60604)
+#define ANSELGSET       PIC32_R(0x60608)
+#define ANSELGINV       PIC32_R(0x6060C)
+#define TRISG           PIC32_R(0x60610) /* G: mask of inputs */
+#define TRISGCLR        PIC32_R(0x60614)
+#define TRISGSET        PIC32_R(0x60618)
+#define TRISGINV        PIC32_R(0x6061C)
+#define PORTG           PIC32_R(0x60620) /* G: read inputs, write outputs */
+#define PORTGCLR        PIC32_R(0x60624)
+#define PORTGSET        PIC32_R(0x60628)
+#define PORTGINV        PIC32_R(0x6062C)
+#define LATG            PIC32_R(0x60630) /* G: read/write outputs */
+#define LATGCLR         PIC32_R(0x60634)
+#define LATGSET         PIC32_R(0x60638)
+#define LATGINV         PIC32_R(0x6063C)
+#define ODCG            PIC32_R(0x60640) /* G: open drain configuration */
+#define ODCGCLR         PIC32_R(0x60644)
+#define ODCGSET         PIC32_R(0x60648)
+#define ODCGINV         PIC32_R(0x6064C)
+#define CNPUG           PIC32_R(0x60650) /* G: input pin pull-up enable */
+#define CNPUGCLR        PIC32_R(0x60654)
+#define CNPUGSET        PIC32_R(0x60658)
+#define CNPUGINV        PIC32_R(0x6065C)
+#define CNPDG           PIC32_R(0x60660) /* G: input pin pull-down enable */
+#define CNPDGCLR        PIC32_R(0x60664)
+#define CNPDGSET        PIC32_R(0x60668)
+#define CNPDGINV        PIC32_R(0x6066C)
+#define CNCONG          PIC32_R(0x60670) /* G: interrupt-on-change control */
+#define CNCONGCLR       PIC32_R(0x60674)
+#define CNCONGSET       PIC32_R(0x60678)
+#define CNCONGINV       PIC32_R(0x6067C)
+#define CNENG           PIC32_R(0x60680) /* G: input change interrupt enable */
+#define CNENGCLR        PIC32_R(0x60684)
+#define CNENGSET        PIC32_R(0x60688)
+#define CNENGINV        PIC32_R(0x6068C)
+#define CNSTATG         PIC32_R(0x60690) /* G: status */
+#define CNSTATGCLR      PIC32_R(0x60694)
+#define CNSTATGSET      PIC32_R(0x60698)
+#define CNSTATGINV      PIC32_R(0x6069C)
+
+#define ANSELH          PIC32_R(0x60700) /* Port H: analog select */
+#define ANSELHCLR       PIC32_R(0x60704)
+#define ANSELHSET       PIC32_R(0x60708)
+#define ANSELHINV       PIC32_R(0x6070C)
+#define TRISH           PIC32_R(0x60710) /* H: mask of inputs */
+#define TRISHCLR        PIC32_R(0x60714)
+#define TRISHSET        PIC32_R(0x60718)
+#define TRISHINV        PIC32_R(0x6071C)
+#define PORTH           PIC32_R(0x60720) /* H: read inputs, write outputs */
+#define PORTHCLR        PIC32_R(0x60724)
+#define PORTHSET        PIC32_R(0x60728)
+#define PORTHINV        PIC32_R(0x6072C)
+#define LATH            PIC32_R(0x60730) /* H: read/write outputs */
+#define LATHCLR         PIC32_R(0x60734)
+#define LATHSET         PIC32_R(0x60738)
+#define LATHINV         PIC32_R(0x6073C)
+#define ODCH            PIC32_R(0x60740) /* H: open drain configuration */
+#define ODCHCLR         PIC32_R(0x60744)
+#define ODCHSET         PIC32_R(0x60748)
+#define ODCHINV         PIC32_R(0x6074C)
+#define CNPUH           PIC32_R(0x60750) /* H: input pin pull-up enable */
+#define CNPUHCLR        PIC32_R(0x60754)
+#define CNPUHSET        PIC32_R(0x60758)
+#define CNPUHINV        PIC32_R(0x6075C)
+#define CNPDH           PIC32_R(0x60760) /* H: input pin pull-down enable */
+#define CNPDHCLR        PIC32_R(0x60764)
+#define CNPDHSET        PIC32_R(0x60768)
+#define CNPDHINV        PIC32_R(0x6076C)
+#define CNCONH          PIC32_R(0x60770) /* H: interrupt-on-change control */
+#define CNCONHCLR       PIC32_R(0x60774)
+#define CNCONHSET       PIC32_R(0x60778)
+#define CNCONHINV       PIC32_R(0x6077C)
+#define CNENH           PIC32_R(0x60780) /* H: input change interrupt enable */
+#define CNENHCLR        PIC32_R(0x60784)
+#define CNENHSET        PIC32_R(0x60788)
+#define CNENHINV        PIC32_R(0x6078C)
+#define CNSTATH         PIC32_R(0x60790) /* H: status */
+#define CNSTATHCLR      PIC32_R(0x60794)
+#define CNSTATHSET      PIC32_R(0x60798)
+#define CNSTATHINV      PIC32_R(0x6079C)
+
+#define ANSELJ          PIC32_R(0x60800) /* Port J: analog select */
+#define ANSELJCLR       PIC32_R(0x60804)
+#define ANSELJSET       PIC32_R(0x60808)
+#define ANSELJINV       PIC32_R(0x6080C)
+#define TRISJ           PIC32_R(0x60810) /* J: mask of inputs */
+#define TRISJCLR        PIC32_R(0x60814)
+#define TRISJSET        PIC32_R(0x60818)
+#define TRISJINV        PIC32_R(0x6081C)
+#define PORTJ           PIC32_R(0x60820) /* J: read inputs, write outputs */
+#define PORTJCLR        PIC32_R(0x60824)
+#define PORTJSET        PIC32_R(0x60828)
+#define PORTJINV        PIC32_R(0x6082C)
+#define LATJ            PIC32_R(0x60830) /* J: read/write outputs */
+#define LATJCLR         PIC32_R(0x60834)
+#define LATJSET         PIC32_R(0x60838)
+#define LATJINV         PIC32_R(0x6083C)
+#define ODCJ            PIC32_R(0x60840) /* J: open drain configuration */
+#define ODCJCLR         PIC32_R(0x60844)
+#define ODCJSET         PIC32_R(0x60848)
+#define ODCJINV         PIC32_R(0x6084C)
+#define CNPUJ           PIC32_R(0x60850) /* J: input pin pull-up enable */
+#define CNPUJCLR        PIC32_R(0x60854)
+#define CNPUJSET        PIC32_R(0x60858)
+#define CNPUJINV        PIC32_R(0x6085C)
+#define CNPDJ           PIC32_R(0x60860) /* J: input pin pull-down enable */
+#define CNPDJCLR        PIC32_R(0x60864)
+#define CNPDJSET        PIC32_R(0x60868)
+#define CNPDJINV        PIC32_R(0x6086C)
+#define CNCONJ          PIC32_R(0x60870) /* J: interrupt-on-change control */
+#define CNCONJCLR       PIC32_R(0x60874)
+#define CNCONJSET       PIC32_R(0x60878)
+#define CNCONJINV       PIC32_R(0x6087C)
+#define CNENJ           PIC32_R(0x60880) /* J: input change interrupt enable */
+#define CNENJCLR        PIC32_R(0x60884)
+#define CNENJSET        PIC32_R(0x60888)
+#define CNENJINV        PIC32_R(0x6088C)
+#define CNSTATJ         PIC32_R(0x60890) /* J: status */
+#define CNSTATJCLR      PIC32_R(0x60894)
+#define CNSTATJSET      PIC32_R(0x60898)
+#define CNSTATJINV      PIC32_R(0x6089C)
+
+#define TRISK           PIC32_R(0x60910) /* Port K: mask of inputs */
+#define TRISKCLR        PIC32_R(0x60914)
+#define TRISKSET        PIC32_R(0x60918)
+#define TRISKINV        PIC32_R(0x6091C)
+#define PORTK           PIC32_R(0x60920) /* K: read inputs, write outputs */
+#define PORTKCLR        PIC32_R(0x60924)
+#define PORTKSET        PIC32_R(0x60928)
+#define PORTKINV        PIC32_R(0x6092C)
+#define LATK            PIC32_R(0x60930) /* K: read/write outputs */
+#define LATKCLR         PIC32_R(0x60934)
+#define LATKSET         PIC32_R(0x60938)
+#define LATKINV         PIC32_R(0x6093C)
+#define ODCK            PIC32_R(0x60940) /* K: open drain configuration */
+#define ODCKCLR         PIC32_R(0x60944)
+#define ODCKSET         PIC32_R(0x60948)
+#define ODCKINV         PIC32_R(0x6094C)
+#define CNPUK           PIC32_R(0x60950) /* K: input pin pull-up enable */
+#define CNPUKCLR        PIC32_R(0x60954)
+#define CNPUKSET        PIC32_R(0x60958)
+#define CNPUKINV        PIC32_R(0x6095C)
+#define CNPDK           PIC32_R(0x60960) /* K: input pin pull-down enable */
+#define CNPDKCLR        PIC32_R(0x60964)
+#define CNPDKSET        PIC32_R(0x60968)
+#define CNPDKINV        PIC32_R(0x6096C)
+#define CNCONK          PIC32_R(0x60970) /* K: interrupt-on-change control */
+#define CNCONKCLR       PIC32_R(0x60974)
+#define CNCONKSET       PIC32_R(0x60978)
+#define CNCONKINV       PIC32_R(0x6097C)
+#define CNENK           PIC32_R(0x60980) /* K: input change interrupt enable */
+#define CNENKCLR        PIC32_R(0x60984)
+#define CNENKSET        PIC32_R(0x60988)
+#define CNENKINV        PIC32_R(0x6098C)
+#define CNSTATK         PIC32_R(0x60990) /* K: status */
+#define CNSTATKCLR      PIC32_R(0x60994)
+#define CNSTATKSET      PIC32_R(0x60998)
+#define CNSTATKINV      PIC32_R(0x6099C)
+
+/*--------------------------------------
+ * Timer registers.
+ */
+#define T1CON           PIC32_R(0x40000) /* Timer 1: Control */
+#define T1CONCLR        PIC32_R(0x40004)
+#define T1CONSET        PIC32_R(0x40008)
+#define T1CONINV        PIC32_R(0x4000C)
+#define TMR1            PIC32_R(0x40010) /* Timer 1: Count */
+#define TMR1CLR         PIC32_R(0x40014)
+#define TMR1SET         PIC32_R(0x40018)
+#define TMR1INV         PIC32_R(0x4001C)
+#define PR1             PIC32_R(0x40020) /* Timer 1: Period register */
+#define PR1CLR          PIC32_R(0x40024)
+#define PR1SET          PIC32_R(0x40028)
+#define PR1INV          PIC32_R(0x4002C)
+#define T2CON           PIC32_R(0x40200) /* Timer 2: Control */
+#define T2CONCLR        PIC32_R(0x40204)
+#define T2CONSET        PIC32_R(0x40208)
+#define T2CONINV        PIC32_R(0x4020C)
+#define TMR2            PIC32_R(0x40210) /* Timer 2: Count */
+#define TMR2CLR         PIC32_R(0x40214)
+#define TMR2SET         PIC32_R(0x40218)
+#define TMR2INV         PIC32_R(0x4021C)
+#define PR2             PIC32_R(0x40220) /* Timer 2: Period register */
+#define PR2CLR          PIC32_R(0x40224)
+#define PR2SET          PIC32_R(0x40228)
+#define PR2INV          PIC32_R(0x4022C)
+#define T3CON           PIC32_R(0x40400) /* Timer 3: Control */
+#define T3CONCLR        PIC32_R(0x40404)
+#define T3CONSET        PIC32_R(0x40408)
+#define T3CONINV        PIC32_R(0x4040C)
+#define TMR3            PIC32_R(0x40410) /* Timer 3: Count */
+#define TMR3CLR         PIC32_R(0x40414)
+#define TMR3SET         PIC32_R(0x40418)
+#define TMR3INV         PIC32_R(0x4041C)
+#define PR3             PIC32_R(0x40420) /* Timer 3: Period register */
+#define PR3CLR          PIC32_R(0x40424)
+#define PR3SET          PIC32_R(0x40428)
+#define PR3INV          PIC32_R(0x4042C)
+#define T4CON           PIC32_R(0x40600) /* Timer 4: Control */
+#define T4CONCLR        PIC32_R(0x40604)
+#define T4CONSET        PIC32_R(0x40608)
+#define T4CONINV        PIC32_R(0x4060C)
+#define TMR4            PIC32_R(0x40610) /* Timer 4: Count */
+#define TMR4CLR         PIC32_R(0x40614)
+#define TMR4SET         PIC32_R(0x40618)
+#define TMR4INV         PIC32_R(0x4061C)
+#define PR4             PIC32_R(0x40620) /* Timer 4: Period register */
+#define PR4CLR          PIC32_R(0x40624)
+#define PR4SET          PIC32_R(0x40628)
+#define PR4INV          PIC32_R(0x4062C)
+#define T5CON           PIC32_R(0x40800) /* Timer 5: Control */
+#define T5CONCLR        PIC32_R(0x40804)
+#define T5CONSET        PIC32_R(0x40808)
+#define T5CONINV        PIC32_R(0x4080C)
+#define TMR5            PIC32_R(0x40810) /* Timer 5: Count */
+#define TMR5CLR         PIC32_R(0x40814)
+#define TMR5SET         PIC32_R(0x40818)
+#define TMR5INV         PIC32_R(0x4081C)
+#define PR5             PIC32_R(0x40820) /* Timer 5: Period register */
+#define PR5CLR          PIC32_R(0x40824)
+#define PR5SET          PIC32_R(0x40828)
+#define PR5INV          PIC32_R(0x4082C)
+#define T6CON           PIC32_R(0x40A00) /* Timer 6: Control */
+#define T6CONCLR        PIC32_R(0x40A04)
+#define T6CONSET        PIC32_R(0x40A08)
+#define T6CONINV        PIC32_R(0x40A0C)
+#define TMR6            PIC32_R(0x40A10) /* Timer 6: Count */
+#define TMR6CLR         PIC32_R(0x40A14)
+#define TMR6SET         PIC32_R(0x40A18)
+#define TMR6INV         PIC32_R(0x40A1C)
+#define PR6             PIC32_R(0x40A20) /* Timer 6: Period register */
+#define PR6CLR          PIC32_R(0x40A24)
+#define PR6SET          PIC32_R(0x40A28)
+#define PR6INV          PIC32_R(0x40A2C)
+#define T7CON           PIC32_R(0x40C00) /* Timer 7: Control */
+#define T7CONCLR        PIC32_R(0x40C04)
+#define T7CONSET        PIC32_R(0x40C08)
+#define T7CONINV        PIC32_R(0x40C0C)
+#define TMR7            PIC32_R(0x40C10) /* Timer 7: Count */
+#define TMR7CLR         PIC32_R(0x40C14)
+#define TMR7SET         PIC32_R(0x40C18)
+#define TMR7INV         PIC32_R(0x40C1C)
+#define PR7             PIC32_R(0x40C20) /* Timer 7: Period register */
+#define PR7CLR          PIC32_R(0x40C24)
+#define PR7SET          PIC32_R(0x40C28)
+#define PR7INV          PIC32_R(0x40C2C)
+#define T8CON           PIC32_R(0x40E00) /* Timer 8: Control */
+#define T8CONCLR        PIC32_R(0x40E04)
+#define T8CONSET        PIC32_R(0x40E08)
+#define T8CONINV        PIC32_R(0x40E0C)
+#define TMR8            PIC32_R(0x40E10) /* Timer 8: Count */
+#define TMR8CLR         PIC32_R(0x40E14)
+#define TMR8SET         PIC32_R(0x40E18)
+#define TMR8INV         PIC32_R(0x40E1C)
+#define PR8             PIC32_R(0x40E20) /* Timer 8: Period register */
+#define PR8CLR          PIC32_R(0x40E24)
+#define PR8SET          PIC32_R(0x40E28)
+#define PR8INV          PIC32_R(0x40E2C)
+#define T9CON           PIC32_R(0x41000) /* Timer 9: Control */
+#define T9CONCLR        PIC32_R(0x41004)
+#define T9CONSET        PIC32_R(0x41008)
+#define T9CONINV        PIC32_R(0x4100C)
+#define TMR9            PIC32_R(0x41010) /* Timer 9: Count */
+#define TMR9CLR         PIC32_R(0x41014)
+#define TMR9SET         PIC32_R(0x41018)
+#define TMR9INV         PIC32_R(0x4101C)
+#define PR9             PIC32_R(0x41020) /* Timer 9: Period register */
+#define PR9CLR          PIC32_R(0x41024)
+#define PR9SET          PIC32_R(0x41028)
+#define PR9INV          PIC32_R(0x4102C)
+
+/*--------------------------------------
+ * Parallel master port registers.
+ */
+#define PMCON           PIC32_R(0x2E000) /* Control */
+#define PMCONCLR        PIC32_R(0x2E004)
+#define PMCONSET        PIC32_R(0x2E008)
+#define PMCONINV        PIC32_R(0x2E00C)
+#define PMMODE          PIC32_R(0x2E010) /* Mode */
+#define PMMODECLR       PIC32_R(0x2E014)
+#define PMMODESET       PIC32_R(0x2E018)
+#define PMMODEINV       PIC32_R(0x2E01C)
+#define PMADDR          PIC32_R(0x2E020) /* Address */
+#define PMADDRCLR       PIC32_R(0x2E024)
+#define PMADDRSET       PIC32_R(0x2E028)
+#define PMADDRINV       PIC32_R(0x2E02C)
+#define PMDOUT          PIC32_R(0x2E030) /* Data output */
+#define PMDOUTCLR       PIC32_R(0x2E034)
+#define PMDOUTSET       PIC32_R(0x2E038)
+#define PMDOUTINV       PIC32_R(0x2E03C)
+#define PMDIN           PIC32_R(0x2E040) /* Data input */
+#define PMDINCLR        PIC32_R(0x2E044)
+#define PMDINSET        PIC32_R(0x2E048)
+#define PMDININV        PIC32_R(0x2E04C)
+#define PMAEN           PIC32_R(0x2E050) /* Pin enable */
+#define PMAENCLR        PIC32_R(0x2E054)
+#define PMAENSET        PIC32_R(0x2E058)
+#define PMAENINV        PIC32_R(0x2E05C)
+#define PMSTAT          PIC32_R(0x2E060) /* Status (slave only) */
+#define PMSTATCLR       PIC32_R(0x2E064)
+#define PMSTATSET       PIC32_R(0x2E068)
+#define PMSTATINV       PIC32_R(0x2E06C)
+
+/*
+ * PMP Control register.
+ */
+#define PIC32_PMCON_RDSP        0x0001 /* Read strobe polarity active-high */
+#define PIC32_PMCON_WRSP        0x0002 /* Write strobe polarity active-high */
+#define PIC32_PMCON_CS1P        0x0008 /* Chip select 0 polarity active-high */
+#define PIC32_PMCON_CS2P        0x0010 /* Chip select 1 polarity active-high */
+#define PIC32_PMCON_ALP         0x0020 /* Address latch polarity active-high */
+#define PIC32_PMCON_CSF         0x00C0 /* Chip select function bitmask: */
+#define PIC32_PMCON_CSF_NONE    0x0000 /* PMCS2 and PMCS1 as A[15:14] */
+#define PIC32_PMCON_CSF_CS2     0x0040 /* PMCS2 as chip select */
+#define PIC32_PMCON_CSF_CS21    0x0080 /* PMCS2 and PMCS1 as chip select */
+#define PIC32_PMCON_PTRDEN      0x0100 /* Read/write strobe port enable */
+#define PIC32_PMCON_PTWREN      0x0200 /* Write enable strobe port enable */
+#define PIC32_PMCON_PMPTTL      0x0400 /* TTL input buffer select */
+#define PIC32_PMCON_ADRMUX      0x1800 /* Address/data mux selection bitmask: */
+#define PIC32_PMCON_ADRMUX_NONE 0x0000 /* Address and data separate */
+#define PIC32_PMCON_ADRMUX_AD   0x0800 /* Lower address on PMD[7:0],
+                                        * high on PMA[15:8] */
+#define PIC32_PMCON_ADRMUX_D8   0x1000 /* All address on PMD[7:0] */
+#define PIC32_PMCON_ADRMUX_D16  0x1800 /* All address on PMD[15:0] */
+#define PIC32_PMCON_SIDL        0x2000 /* Stop in idle */
+#define PIC32_PMCON_FRZ         0x4000 /* Freeze in debug exception */
+#define PIC32_PMCON_ON          0x8000 /* Parallel master port enable */
+
+/*
+ * PMP Mode register.
+ */
+#define PIC32_PMMODE_WAITE(x)   ((x)<<0) /* Wait states: data hold
+                                          * after RW strobe */
+#define PIC32_PMMODE_WAITM(x)   ((x)<<2) /* Wait states: data RW strobe */
+#define PIC32_PMMODE_WAITB(x)   ((x)<<6) /* Wait states: data setup
+                                            * to RW strobe */
+#define PIC32_PMMODE_MODE       0x0300  /* Mode select bitmask: */
+#define PIC32_PMMODE_MODE_SLAVE 0x0000  /* Legacy slave */
+#define PIC32_PMMODE_MODE_SLENH 0x0100  /* Enhanced slave */
+#define PIC32_PMMODE_MODE_MAST2 0x0200  /* Master mode 2 */
+#define PIC32_PMMODE_MODE_MAST1 0x0300  /* Master mode 1 */
+#define PIC32_PMMODE_MODE16     0x0400  /* 16-bit mode */
+#define PIC32_PMMODE_INCM       0x1800  /* Address increment mode bitmask: */
+#define PIC32_PMMODE_INCM_NONE  0x0000  /* No increment/decrement */
+#define PIC32_PMMODE_INCM_INC   0x0800  /* Increment address */
+#define PIC32_PMMODE_INCM_DEC   0x1000  /* Decrement address */
+#define PIC32_PMMODE_INCM_SLAVE 0x1800  /* Slave auto-increment */
+#define PIC32_PMMODE_IRQM       0x6000  /* Interrupt request bitmask: */
+#define PIC32_PMMODE_IRQM_DIS   0x0000  /* No interrupt generated */
+#define PIC32_PMMODE_IRQM_END   0x2000  /* Interrupt at end of r/w cycle */
+#define PIC32_PMMODE_IRQM_A3    0x4000  /* Interrupt on address 3 */
+#define PIC32_PMMODE_BUSY       0x8000  /* Port is busy */
+
+/*
+ * PMP Address register.
+ */
+#define PIC32_PMADDR_PADDR      0x3FFF /* Destination address */
+#define PIC32_PMADDR_CS1        0x4000 /* Chip select 1 is active */
+#define PIC32_PMADDR_CS2        0x8000 /* Chip select 2 is active */
+
+/*
+ * PMP status register (slave only).
+ */
+#define PIC32_PMSTAT_OB0E       0x0001 /* Output buffer 0 empty */
+#define PIC32_PMSTAT_OB1E       0x0002 /* Output buffer 1 empty */
+#define PIC32_PMSTAT_OB2E       0x0004 /* Output buffer 2 empty */
+#define PIC32_PMSTAT_OB3E       0x0008 /* Output buffer 3 empty */
+#define PIC32_PMSTAT_OBUF       0x0040 /* Output buffer underflow */
+#define PIC32_PMSTAT_OBE        0x0080 /* Output buffer empty */
+#define PIC32_PMSTAT_IB0F       0x0100 /* Input buffer 0 full */
+#define PIC32_PMSTAT_IB1F       0x0200 /* Input buffer 1 full */
+#define PIC32_PMSTAT_IB2F       0x0400 /* Input buffer 2 full */
+#define PIC32_PMSTAT_IB3F       0x0800 /* Input buffer 3 full */
+#define PIC32_PMSTAT_IBOV       0x4000 /* Input buffer overflow */
+#define PIC32_PMSTAT_IBF        0x8000 /* Input buffer full */
+
+/*--------------------------------------
+ * UART registers.
+ */
+#define U1MODE          PIC32_R(0x22000) /* Mode */
+#define U1MODECLR       PIC32_R(0x22004)
+#define U1MODESET       PIC32_R(0x22008)
+#define U1MODEINV       PIC32_R(0x2200C)
+#define U1STA           PIC32_R(0x22010) /* Status and control */
+#define U1STACLR        PIC32_R(0x22014)
+#define U1STASET        PIC32_R(0x22018)
+#define U1STAINV        PIC32_R(0x2201C)
+#define U1TXREG         PIC32_R(0x22020) /* Transmit */
+#define U1RXREG         PIC32_R(0x22030) /* Receive */
+#define U1BRG           PIC32_R(0x22040) /* Baud rate */
+#define U1BRGCLR        PIC32_R(0x22044)
+#define U1BRGSET        PIC32_R(0x22048)
+#define U1BRGINV        PIC32_R(0x2204C)
+
+#define U2MODE          PIC32_R(0x22200) /* Mode */
+#define U2MODECLR       PIC32_R(0x22204)
+#define U2MODESET       PIC32_R(0x22208)
+#define U2MODEINV       PIC32_R(0x2220C)
+#define U2STA           PIC32_R(0x22210) /* Status and control */
+#define U2STACLR        PIC32_R(0x22214)
+#define U2STASET        PIC32_R(0x22218)
+#define U2STAINV        PIC32_R(0x2221C)
+#define U2TXREG         PIC32_R(0x22220) /* Transmit */
+#define U2RXREG         PIC32_R(0x22230) /* Receive */
+#define U2BRG           PIC32_R(0x22240) /* Baud rate */
+#define U2BRGCLR        PIC32_R(0x22244)
+#define U2BRGSET        PIC32_R(0x22248)
+#define U2BRGINV        PIC32_R(0x2224C)
+
+#define U3MODE          PIC32_R(0x22400) /* Mode */
+#define U3MODECLR       PIC32_R(0x22404)
+#define U3MODESET       PIC32_R(0x22408)
+#define U3MODEINV       PIC32_R(0x2240C)
+#define U3STA           PIC32_R(0x22410) /* Status and control */
+#define U3STACLR        PIC32_R(0x22414)
+#define U3STASET        PIC32_R(0x22418)
+#define U3STAINV        PIC32_R(0x2241C)
+#define U3TXREG         PIC32_R(0x22420) /* Transmit */
+#define U3RXREG         PIC32_R(0x22430) /* Receive */
+#define U3BRG           PIC32_R(0x22440) /* Baud rate */
+#define U3BRGCLR        PIC32_R(0x22444)
+#define U3BRGSET        PIC32_R(0x22448)
+#define U3BRGINV        PIC32_R(0x2244C)
+
+#define U4MODE          PIC32_R(0x22600) /* Mode */
+#define U4MODECLR       PIC32_R(0x22604)
+#define U4MODESET       PIC32_R(0x22608)
+#define U4MODEINV       PIC32_R(0x2260C)
+#define U4STA           PIC32_R(0x22610) /* Status and control */
+#define U4STACLR        PIC32_R(0x22614)
+#define U4STASET        PIC32_R(0x22618)
+#define U4STAINV        PIC32_R(0x2261C)
+#define U4TXREG         PIC32_R(0x22620) /* Transmit */
+#define U4RXREG         PIC32_R(0x22630) /* Receive */
+#define U4BRG           PIC32_R(0x22640) /* Baud rate */
+#define U4BRGCLR        PIC32_R(0x22644)
+#define U4BRGSET        PIC32_R(0x22648)
+#define U4BRGINV        PIC32_R(0x2264C)
+
+#define U5MODE          PIC32_R(0x22800) /* Mode */
+#define U5MODECLR       PIC32_R(0x22804)
+#define U5MODESET       PIC32_R(0x22808)
+#define U5MODEINV       PIC32_R(0x2280C)
+#define U5STA           PIC32_R(0x22810) /* Status and control */
+#define U5STACLR        PIC32_R(0x22814)
+#define U5STASET        PIC32_R(0x22818)
+#define U5STAINV        PIC32_R(0x2281C)
+#define U5TXREG         PIC32_R(0x22820) /* Transmit */
+#define U5RXREG         PIC32_R(0x22830) /* Receive */
+#define U5BRG           PIC32_R(0x22840) /* Baud rate */
+#define U5BRGCLR        PIC32_R(0x22844)
+#define U5BRGSET        PIC32_R(0x22848)
+#define U5BRGINV        PIC32_R(0x2284C)
+
+#define U6MODE          PIC32_R(0x22A00) /* Mode */
+#define U6MODECLR       PIC32_R(0x22A04)
+#define U6MODESET       PIC32_R(0x22A08)
+#define U6MODEINV       PIC32_R(0x22A0C)
+#define U6STA           PIC32_R(0x22A10) /* Status and control */
+#define U6STACLR        PIC32_R(0x22A14)
+#define U6STASET        PIC32_R(0x22A18)
+#define U6STAINV        PIC32_R(0x22A1C)
+#define U6TXREG         PIC32_R(0x22A20) /* Transmit */
+#define U6RXREG         PIC32_R(0x22A30) /* Receive */
+#define U6BRG           PIC32_R(0x22A40) /* Baud rate */
+#define U6BRGCLR        PIC32_R(0x22A44)
+#define U6BRGSET        PIC32_R(0x22A48)
+#define U6BRGINV        PIC32_R(0x22A4C)
+
+/*
+ * UART Mode register.
+ */
+#define PIC32_UMODE_STSEL       0x0001  /* 2 Stop bits */
+#define PIC32_UMODE_PDSEL       0x0006  /* Bitmask: */
+#define PIC32_UMODE_PDSEL_8NPAR 0x0000  /* 8-bit data, no parity */
+#define PIC32_UMODE_PDSEL_8EVEN 0x0002  /* 8-bit data, even parity */
+#define PIC32_UMODE_PDSEL_8ODD  0x0004  /* 8-bit data, odd parity */
+#define PIC32_UMODE_PDSEL_9NPAR 0x0006  /* 9-bit data, no parity */
+#define PIC32_UMODE_BRGH        0x0008  /* High Baud Rate Enable */
+#define PIC32_UMODE_RXINV       0x0010  /* Receive Polarity Inversion */
+#define PIC32_UMODE_ABAUD       0x0020  /* Auto-Baud Enable */
+#define PIC32_UMODE_LPBACK      0x0040  /* UARTx Loopback Mode */
+#define PIC32_UMODE_WAKE        0x0080  /* Wake-up on start bit
+                                         * during Sleep Mode */
+#define PIC32_UMODE_UEN         0x0300  /* Bitmask: */
+#define PIC32_UMODE_UEN_RTS     0x0100  /* Using UxRTS pin */
+#define PIC32_UMODE_UEN_RTSCTS  0x0200  /* Using UxCTS and UxRTS pins */
+#define PIC32_UMODE_UEN_BCLK    0x0300  /* Using UxBCLK pin */
+#define PIC32_UMODE_RTSMD       0x0800  /* UxRTS Pin Simplex mode */
+#define PIC32_UMODE_IREN        0x1000  /* IrDA Encoder and Decoder Enable */
+#define PIC32_UMODE_SIDL        0x2000  /* Stop in Idle Mode */
+#define PIC32_UMODE_FRZ         0x4000  /* Freeze in Debug Exception Mode */
+#define PIC32_UMODE_ON          0x8000  /* UART Enable */
+
+/*
+ * UART Control and status register.
+ */
+#define PIC32_USTA_URXDA        0x00000001 /* Receive Data Available (ro) */
+#define PIC32_USTA_OERR         0x00000002 /* Receive Buffer Overrun */
+#define PIC32_USTA_FERR         0x00000004 /* Framing error detected (ro) */
+#define PIC32_USTA_PERR         0x00000008 /* Parity error detected (ro) */
+#define PIC32_USTA_RIDLE        0x00000010 /* Receiver is idle (ro) */
+#define PIC32_USTA_ADDEN        0x00000020 /* Address Detect mode */
+#define PIC32_USTA_URXISEL      0x000000C0 /* Bitmask: RX interrupt when... */
+#define PIC32_USTA_URXISEL_NEMP 0x00000000 /* ...receive buffer is not empty */
+#define PIC32_USTA_URXISEL_HALF 0x00000040 /* ...RX buffer becomes 1/2 full */
+#define PIC32_USTA_URXISEL_3_4  0x00000080 /* ...RX buffer becomes 3/4 full */
+#define PIC32_USTA_TRMT         0x00000100 /* TX shift register empty (ro) */
+#define PIC32_USTA_UTXBF        0x00000200 /* Transmit buffer is full (ro) */
+#define PIC32_USTA_UTXEN        0x00000400 /* Transmit Enable */
+#define PIC32_USTA_UTXBRK       0x00000800 /* Transmit Break */
+#define PIC32_USTA_URXEN        0x00001000 /* Receiver Enable */
+#define PIC32_USTA_UTXINV       0x00002000 /* Transmit Polarity Inversion */
+#define PIC32_USTA_UTXISEL      0x0000C000 /* Bitmask: TX interrupt when... */
+#define PIC32_USTA_UTXISEL_1    0x00000000 /* ...at least 1 empty space */
+#define PIC32_USTA_UTXISEL_ALL  0x00004000 /* ...all characters transmitted */
+#define PIC32_USTA_UTXISEL_EMP  0x00008000 /* ...the TX buffer becomes empty */
+#define PIC32_USTA_ADDR         0x00FF0000 /* Automatic Address Mask */
+#define PIC32_USTA_ADM_EN       0x01000000 /* Automatic Address Detect */
+
+/*
+ * Compute the 16-bit baud rate divisor, given
+ * the bus frequency and baud rate.
+ * Round to the nearest integer.
+ */
+#define PIC32_BRG_BAUD(fr, bd)  ((((fr)/8 + (bd)) / (bd) / 2) - 1)
+
+/*--------------------------------------
+ * Peripheral port select registers.
+ */
+#define INT1R           PIC32_R(0x1404)
+#define INT2R           PIC32_R(0x1408)
+#define INT3R           PIC32_R(0x140C)
+#define INT4R           PIC32_R(0x1410)
+#define T2CKR           PIC32_R(0x1418)
+#define T3CKR           PIC32_R(0x141C)
+#define T4CKR           PIC32_R(0x1420)
+#define T5CKR           PIC32_R(0x1424)
+#define T6CKR           PIC32_R(0x1428)
+#define T7CKR           PIC32_R(0x142C)
+#define T8CKR           PIC32_R(0x1430)
+#define T9CKR           PIC32_R(0x1434)
+#define IC1R            PIC32_R(0x1438)
+#define IC2R            PIC32_R(0x143C)
+#define IC3R            PIC32_R(0x1440)
+#define IC4R            PIC32_R(0x1444)
+#define IC5R            PIC32_R(0x1448)
+#define IC6R            PIC32_R(0x144C)
+#define IC7R            PIC32_R(0x1450)
+#define IC8R            PIC32_R(0x1454)
+#define IC9R            PIC32_R(0x1458)
+#define OCFAR           PIC32_R(0x1460)
+#define U1RXR           PIC32_R(0x1468)
+#define U1CTSR          PIC32_R(0x146C)
+#define U2RXR           PIC32_R(0x1470)
+#define U2CTSR          PIC32_R(0x1474)
+#define U3RXR           PIC32_R(0x1478)
+#define U3CTSR          PIC32_R(0x147C)
+#define U4RXR           PIC32_R(0x1480)
+#define U4CTSR          PIC32_R(0x1484)
+#define U5RXR           PIC32_R(0x1488)
+#define U5CTSR          PIC32_R(0x148C)
+#define U6RXR           PIC32_R(0x1490)
+#define U6CTSR          PIC32_R(0x1494)
+#define SDI1R           PIC32_R(0x149C)
+#define SS1R            PIC32_R(0x14A0)
+#define SDI2R           PIC32_R(0x14A8)
+#define SS2R            PIC32_R(0x14AC)
+#define SDI3R           PIC32_R(0x14B4)
+#define SS3R            PIC32_R(0x14B8)
+#define SDI4R           PIC32_R(0x14C0)
+#define SS4R            PIC32_R(0x14C4)
+#define SDI5R           PIC32_R(0x14CC)
+#define SS5R            PIC32_R(0x14D0)
+#define SDI6R           PIC32_R(0x14D8)
+#define SS6R            PIC32_R(0x14DC)
+#define C1RXR           PIC32_R(0x14E0)
+#define C2RXR           PIC32_R(0x14E4)
+#define REFCLKI1R       PIC32_R(0x14E8)
+#define REFCLKI3R       PIC32_R(0x14F0)
+#define REFCLKI4R       PIC32_R(0x14F4)
+
+#define RPA14R          PIC32_R(0x1538)
+#define RPA15R          PIC32_R(0x153C)
+#define RPB0R           PIC32_R(0x1540)
+#define RPB1R           PIC32_R(0x1544)
+#define RPB2R           PIC32_R(0x1548)
+#define RPB3R           PIC32_R(0x154C)
+#define RPB5R           PIC32_R(0x1554)
+#define RPB6R           PIC32_R(0x1558)
+#define RPB7R           PIC32_R(0x155C)
+#define RPB8R           PIC32_R(0x1560)
+#define RPB9R           PIC32_R(0x1564)
+#define RPB10R          PIC32_R(0x1568)
+#define RPB14R          PIC32_R(0x1578)
+#define RPB15R          PIC32_R(0x157C)
+#define RPC1R           PIC32_R(0x1584)
+#define RPC2R           PIC32_R(0x1588)
+#define RPC3R           PIC32_R(0x158C)
+#define RPC4R           PIC32_R(0x1590)
+#define RPC13R          PIC32_R(0x15B4)
+#define RPC14R          PIC32_R(0x15B8)
+#define RPD0R           PIC32_R(0x15C0)
+#define RPD1R           PIC32_R(0x15C4)
+#define RPD2R           PIC32_R(0x15C8)
+#define RPD3R           PIC32_R(0x15CC)
+#define RPD4R           PIC32_R(0x15D0)
+#define RPD5R           PIC32_R(0x15D4)
+#define RPD6R           PIC32_R(0x15D8)
+#define RPD7R           PIC32_R(0x15DC)
+#define RPD9R           PIC32_R(0x15E4)
+#define RPD10R          PIC32_R(0x15E8)
+#define RPD11R          PIC32_R(0x15EC)
+#define RPD12R          PIC32_R(0x15F0)
+#define RPD14R          PIC32_R(0x15F8)
+#define RPD15R          PIC32_R(0x15FC)
+#define RPE3R           PIC32_R(0x160C)
+#define RPE5R           PIC32_R(0x1614)
+#define RPE8R           PIC32_R(0x1620)
+#define RPE9R           PIC32_R(0x1624)
+#define RPF0R           PIC32_R(0x1640)
+#define RPF1R           PIC32_R(0x1644)
+#define RPF2R           PIC32_R(0x1648)
+#define RPF3R           PIC32_R(0x164C)
+#define RPF4R           PIC32_R(0x1650)
+#define RPF5R           PIC32_R(0x1654)
+#define RPF8R           PIC32_R(0x1660)
+#define RPF12R          PIC32_R(0x1670)
+#define RPF13R          PIC32_R(0x1674)
+#define RPG0R           PIC32_R(0x1680)
+#define RPG1R           PIC32_R(0x1684)
+#define RPG6R           PIC32_R(0x1698)
+#define RPG7R           PIC32_R(0x169C)
+#define RPG8R           PIC32_R(0x16A0)
+#define RPG9R           PIC32_R(0x16A4)
+
+/*--------------------------------------
+ * Prefetch cache controller registers.
+ */
+#define PRECON          PIC32_R(0xe0000)       /* Prefetch cache control */
+#define PRECONCLR       PIC32_R(0xe0004)
+#define PRECONSET       PIC32_R(0xe0008)
+#define PRECONINV       PIC32_R(0xe000C)
+#define PRESTAT         PIC32_R(0xe0010)       /* Prefetch status */
+#define PRESTATCLR      PIC32_R(0xe0014)
+#define PRESTATSET      PIC32_R(0xe0018)
+#define PRESTATINV      PIC32_R(0xe001C)
+/* TODO: other prefetch registers */
+
+/*--------------------------------------
+ * System controller registers.
+ */
+#define CFGCON          PIC32_R(0x0000)
+#define DEVID           PIC32_R(0x0020)
+#define SYSKEY          PIC32_R(0x0030)
+#define CFGEBIA         PIC32_R(0x00c0)
+#define CFGEBIACLR      PIC32_R(0x00c4)
+#define CFGEBIASET      PIC32_R(0x00c8)
+#define CFGEBIAINV      PIC32_R(0x00cc)
+#define CFGEBIC         PIC32_R(0x00d0)
+#define CFGEBICCLR      PIC32_R(0x00d4)
+#define CFGEBICSET      PIC32_R(0x00d8)
+#define CFGEBICINV      PIC32_R(0x00dc)
+#define CFGPG           PIC32_R(0x00e0)
+
+#define OSCCON          PIC32_R(0x1200)    /* Oscillator Control */
+#define OSCTUN          PIC32_R(0x1210)
+#define SPLLCON         PIC32_R(0x1220)
+#define RCON            PIC32_R(0x1240)
+#define RSWRST          PIC32_R(0x1250)
+#define RSWRSTCLR       PIC32_R(0x1254)
+#define RSWRSTSET       PIC32_R(0x1258)
+#define RSWRSTINV       PIC32_R(0x125c)
+#define RNMICON         PIC32_R(0x1260)
+#define PWRCON          PIC32_R(0x1270)
+#define REFO1CON        PIC32_R(0x1280)
+#define REFO1CONCLR     PIC32_R(0x1284)
+#define REFO1CONSET     PIC32_R(0x1288)
+#define REFO1CONINV     PIC32_R(0x128c)
+#define REFO1TRIM       PIC32_R(0x1290)
+#define REFO2CON        PIC32_R(0x12A0)
+#define REFO2CONCLR     PIC32_R(0x12A4)
+#define REFO2CONSET     PIC32_R(0x12A8)
+#define REFO2CONINV     PIC32_R(0x12Ac)
+#define REFO2TRIM       PIC32_R(0x12B0)
+#define REFO3CON        PIC32_R(0x12C0)
+#define REFO3CONCLR     PIC32_R(0x12C4)
+#define REFO3CONSET     PIC32_R(0x12C8)
+#define REFO3CONINV     PIC32_R(0x12Cc)
+#define REFO3TRIM       PIC32_R(0x12D0)
+#define REFO4CON        PIC32_R(0x12E0)
+#define REFO4CONCLR     PIC32_R(0x12E4)
+#define REFO4CONSET     PIC32_R(0x12E8)
+#define REFO4CONINV     PIC32_R(0x12Ec)
+#define REFO4TRIM       PIC32_R(0x12F0)
+#define PB1DIV          PIC32_R(0x1300)
+#define PB1DIVCLR       PIC32_R(0x1304)
+#define PB1DIVSET       PIC32_R(0x1308)
+#define PB1DIVINV       PIC32_R(0x130c)
+#define PB2DIV          PIC32_R(0x1310)
+#define PB2DIVCLR       PIC32_R(0x1314)
+#define PB2DIVSET       PIC32_R(0x1318)
+#define PB2DIVINV       PIC32_R(0x131c)
+#define PB3DIV          PIC32_R(0x1320)
+#define PB3DIVCLR       PIC32_R(0x1324)
+#define PB3DIVSET       PIC32_R(0x1328)
+#define PB3DIVINV       PIC32_R(0x132c)
+#define PB4DIV          PIC32_R(0x1330)
+#define PB4DIVCLR       PIC32_R(0x1334)
+#define PB4DIVSET       PIC32_R(0x1338)
+#define PB4DIVINV       PIC32_R(0x133c)
+#define PB5DIV          PIC32_R(0x1340)
+#define PB5DIVCLR       PIC32_R(0x1344)
+#define PB5DIVSET       PIC32_R(0x1348)
+#define PB5DIVINV       PIC32_R(0x134c)
+#define PB7DIV          PIC32_R(0x1360)
+#define PB7DIVCLR       PIC32_R(0x1364)
+#define PB7DIVSET       PIC32_R(0x1368)
+#define PB7DIVINV       PIC32_R(0x136c)
+#define PB8DIV          PIC32_R(0x1370)
+#define PB8DIVCLR       PIC32_R(0x1374)
+#define PB8DIVSET       PIC32_R(0x1378)
+#define PB8DIVINV       PIC32_R(0x137c)
+
+/*
+ * Configuration Control register.
+ */
+#define PIC32_CFGCON_DMAPRI     0x02000000 /* DMA gets High Priority
+                                            * access to SRAM */
+#define PIC32_CFGCON_CPUPRI     0x01000000 /* CPU gets High Priority
+                                            * access to SRAM */
+#define PIC32_CFGCON_ICACLK     0x00020000 /* Input Capture alternate clock */
+#define PIC32_CFGCON_OCACLK     0x00010000 /* Output Compare alternate clock */
+#define PIC32_CFGCON_IOLOCK     0x00002000 /* Peripheral pin select lock */
+#define PIC32_CFGCON_PMDLOCK    0x00001000 /* Peripheral module disable */
+#define PIC32_CFGCON_PGLOCK     0x00000800 /* Permission group lock */
+#define PIC32_CFGCON_USBSSEN    0x00000100 /* USB suspend sleep enable */
+#define PIC32_CFGCON_ECC_MASK   0x00000030 /* Flash ECC Configuration */
+#define PIC32_CFGCON_ECC_DISWR  0x00000030 /* ECC disabled,
+                                            * ECCCON<1:0> writable */
+#define PIC32_CFGCON_ECC_DISRO  0x00000020 /* ECC disabled,
+                                            * ECCCON<1:0> locked */
+#define PIC32_CFGCON_ECC_DYN    0x00000010 /* Dynamic Flash ECC is enabled */
+#define PIC32_CFGCON_ECC_EN     0x00000000 /* Flash ECC is enabled */
+#define PIC32_CFGCON_JTAGEN     0x00000008 /* JTAG port enable */
+#define PIC32_CFGCON_TROEN      0x00000004 /* Trace output enable */
+#define PIC32_CFGCON_TDOEN      0x00000001 /* 2-wire JTAG protocol uses TDO */
+
+/*--------------------------------------
+ * A/D Converter registers.
+ */
+#define AD1CON1         PIC32_R(0x4b000)   /* Control register 1 */
+#define AD1CON2         PIC32_R(0x4b004)   /* Control register 2 */
+#define AD1CON3         PIC32_R(0x4b008)   /* Control register 3 */
+#define AD1IMOD         PIC32_R(0x4b00c)
+#define AD1GIRQEN1      PIC32_R(0x4b010)
+#define AD1GIRQEN2      PIC32_R(0x4b014)
+#define AD1CSS1         PIC32_R(0x4b018)
+#define AD1CSS2         PIC32_R(0x4b01c)
+#define AD1DSTAT1       PIC32_R(0x4b020)
+#define AD1DSTAT2       PIC32_R(0x4b024)
+#define AD1CMPEN1       PIC32_R(0x4b028)
+#define AD1CMP1         PIC32_R(0x4b02c)
+#define AD1CMPEN2       PIC32_R(0x4b030)
+#define AD1CMP2         PIC32_R(0x4b034)
+#define AD1CMPEN3       PIC32_R(0x4b038)
+#define AD1CMP3         PIC32_R(0x4b03c)
+#define AD1CMPEN4       PIC32_R(0x4b040)
+#define AD1CMP4         PIC32_R(0x4b044)
+#define AD1CMPEN5       PIC32_R(0x4b048)
+#define AD1CMP5         PIC32_R(0x4b04c)
+#define AD1CMPEN6       PIC32_R(0x4b050)
+#define AD1CMP6         PIC32_R(0x4b054)
+#define AD1FLTR1        PIC32_R(0x4b058)
+#define AD1FLTR2        PIC32_R(0x4b05c)
+#define AD1FLTR3        PIC32_R(0x4b060)
+#define AD1FLTR4        PIC32_R(0x4b064)
+#define AD1FLTR5        PIC32_R(0x4b068)
+#define AD1FLTR6        PIC32_R(0x4b06c)
+#define AD1TRG1         PIC32_R(0x4b070)
+#define AD1TRG2         PIC32_R(0x4b074)
+#define AD1TRG3         PIC32_R(0x4b078)
+#define AD1CMPCON1      PIC32_R(0x4b090)
+#define AD1CMPCON2      PIC32_R(0x4b094)
+#define AD1CMPCON3      PIC32_R(0x4b098)
+#define AD1CMPCON4      PIC32_R(0x4b09c)
+#define AD1CMPCON5      PIC32_R(0x4b0a0)
+#define AD1CMPCON6      PIC32_R(0x4b0a4)
+#define AD1DATA0        PIC32_R(0x4b0b8)
+#define AD1DATA1        PIC32_R(0x4b0bc)
+#define AD1DATA2        PIC32_R(0x4b0c0)
+#define AD1DATA3        PIC32_R(0x4b0c4)
+#define AD1DATA4        PIC32_R(0x4b0c8)
+#define AD1DATA5        PIC32_R(0x4b0cc)
+#define AD1DATA6        PIC32_R(0x4b0d0)
+#define AD1DATA7        PIC32_R(0x4b0d4)
+#define AD1DATA8        PIC32_R(0x4b0d8)
+#define AD1DATA9        PIC32_R(0x4b0dc)
+#define AD1DATA10       PIC32_R(0x4b0e0)
+#define AD1DATA11       PIC32_R(0x4b0e4)
+#define AD1DATA12       PIC32_R(0x4b0e8)
+#define AD1DATA13       PIC32_R(0x4b0ec)
+#define AD1DATA14       PIC32_R(0x4b0f0)
+#define AD1DATA15       PIC32_R(0x4b0f4)
+#define AD1DATA16       PIC32_R(0x4b0f8)
+#define AD1DATA17       PIC32_R(0x4b0fc)
+#define AD1DATA18       PIC32_R(0x4b100)
+#define AD1DATA19       PIC32_R(0x4b104)
+#define AD1DATA20       PIC32_R(0x4b108)
+#define AD1DATA21       PIC32_R(0x4b10c)
+#define AD1DATA22       PIC32_R(0x4b110)
+#define AD1DATA23       PIC32_R(0x4b114)
+#define AD1DATA24       PIC32_R(0x4b118)
+#define AD1DATA25       PIC32_R(0x4b11c)
+#define AD1DATA26       PIC32_R(0x4b120)
+#define AD1DATA27       PIC32_R(0x4b124)
+#define AD1DATA28       PIC32_R(0x4b128)
+#define AD1DATA29       PIC32_R(0x4b12c)
+#define AD1DATA30       PIC32_R(0x4b130)
+#define AD1DATA31       PIC32_R(0x4b134)
+#define AD1DATA32       PIC32_R(0x4b138)
+#define AD1DATA33       PIC32_R(0x4b13c)
+#define AD1DATA34       PIC32_R(0x4b140)
+#define AD1DATA35       PIC32_R(0x4b144)
+#define AD1DATA36       PIC32_R(0x4b148)
+#define AD1DATA37       PIC32_R(0x4b14c)
+#define AD1DATA38       PIC32_R(0x4b150)
+#define AD1DATA39       PIC32_R(0x4b154)
+#define AD1DATA40       PIC32_R(0x4b158)
+#define AD1DATA41       PIC32_R(0x4b15c)
+#define AD1DATA42       PIC32_R(0x4b160)
+#define AD1DATA43       PIC32_R(0x4b164)
+#define AD1DATA44       PIC32_R(0x4b168)
+#define AD1CAL1         PIC32_R(0x4b200)   /* Calibration Data */
+#define AD1CAL2         PIC32_R(0x4b204)
+#define AD1CAL3         PIC32_R(0x4b208)
+#define AD1CAL4         PIC32_R(0x4b20c)
+#define AD1CAL5         PIC32_R(0x4b210)
+
+/*--------------------------------------
+ * SPI registers.
+ */
+#define SPI1CON         PIC32_R(0x21000) /* Control */
+#define SPI1CONCLR      PIC32_R(0x21004)
+#define SPI1CONSET      PIC32_R(0x21008)
+#define SPI1CONINV      PIC32_R(0x2100c)
+#define SPI1STAT        PIC32_R(0x21010) /* Status */
+#define SPI1STATCLR     PIC32_R(0x21014)
+#define SPI1STATSET     PIC32_R(0x21018)
+#define SPI1STATINV     PIC32_R(0x2101c)
+#define SPI1BUF         PIC32_R(0x21020) /* Transmit and receive buffer */
+#define SPI1BRG         PIC32_R(0x21030) /* Baud rate generator */
+#define SPI1BRGCLR      PIC32_R(0x21034)
+#define SPI1BRGSET      PIC32_R(0x21038)
+#define SPI1BRGINV      PIC32_R(0x2103c)
+#define SPI1CON2        PIC32_R(0x21040) /* Control 2 */
+#define SPI1CON2CLR     PIC32_R(0x21044)
+#define SPI1CON2SET     PIC32_R(0x21048)
+#define SPI1CON2INV     PIC32_R(0x2104c)
+
+#define SPI2CON         PIC32_R(0x21200) /* Control */
+#define SPI2CONCLR      PIC32_R(0x21204)
+#define SPI2CONSET      PIC32_R(0x21208)
+#define SPI2CONINV      PIC32_R(0x2120c)
+#define SPI2STAT        PIC32_R(0x21210) /* Status */
+#define SPI2STATCLR     PIC32_R(0x21214)
+#define SPI2STATSET     PIC32_R(0x21218)
+#define SPI2STATINV     PIC32_R(0x2121c)
+#define SPI2BUF         PIC32_R(0x21220) /* Transmit and receive buffer */
+#define SPI2BRG         PIC32_R(0x21230) /* Baud rate generator */
+#define SPI2BRGCLR      PIC32_R(0x21234)
+#define SPI2BRGSET      PIC32_R(0x21238)
+#define SPI2BRGINV      PIC32_R(0x2123c)
+#define SPI2CON2        PIC32_R(0x21240) /* Control 2 */
+#define SPI2CON2CLR     PIC32_R(0x21244)
+#define SPI2CON2SET     PIC32_R(0x21248)
+#define SPI2CON2INV     PIC32_R(0x2124c)
+
+#define SPI3CON         PIC32_R(0x21400) /* Control */
+#define SPI3CONCLR      PIC32_R(0x21404)
+#define SPI3CONSET      PIC32_R(0x21408)
+#define SPI3CONINV      PIC32_R(0x2140c)
+#define SPI3STAT        PIC32_R(0x21410) /* Status */
+#define SPI3STATCLR     PIC32_R(0x21414)
+#define SPI3STATSET     PIC32_R(0x21418)
+#define SPI3STATINV     PIC32_R(0x2141c)
+#define SPI3BUF         PIC32_R(0x21420) /* Transmit and receive buffer */
+#define SPI3BRG         PIC32_R(0x21430) /* Baud rate generator */
+#define SPI3BRGCLR      PIC32_R(0x21434)
+#define SPI3BRGSET      PIC32_R(0x21438)
+#define SPI3BRGINV      PIC32_R(0x2143c)
+#define SPI3CON2        PIC32_R(0x21440) /* Control 2 */
+#define SPI3CON2CLR     PIC32_R(0x21444)
+#define SPI3CON2SET     PIC32_R(0x21448)
+#define SPI3CON2INV     PIC32_R(0x2144c)
+
+#define SPI4CON         PIC32_R(0x21600) /* Control */
+#define SPI4CONCLR      PIC32_R(0x21604)
+#define SPI4CONSET      PIC32_R(0x21608)
+#define SPI4CONINV      PIC32_R(0x2160c)
+#define SPI4STAT        PIC32_R(0x21610) /* Status */
+#define SPI4STATCLR     PIC32_R(0x21614)
+#define SPI4STATSET     PIC32_R(0x21618)
+#define SPI4STATINV     PIC32_R(0x2161c)
+#define SPI4BUF         PIC32_R(0x21620) /* Transmit and receive buffer */
+#define SPI4BRG         PIC32_R(0x21630) /* Baud rate generator */
+#define SPI4BRGCLR      PIC32_R(0x21634)
+#define SPI4BRGSET      PIC32_R(0x21638)
+#define SPI4BRGINV      PIC32_R(0x2163c)
+#define SPI4CON2        PIC32_R(0x21640) /* Control 2 */
+#define SPI4CON2CLR     PIC32_R(0x21644)
+#define SPI4CON2SET     PIC32_R(0x21648)
+#define SPI4CON2INV     PIC32_R(0x2164c)
+
+#define SPI5CON         PIC32_R(0x21800) /* Control */
+#define SPI5CONCLR      PIC32_R(0x21804)
+#define SPI5CONSET      PIC32_R(0x21808)
+#define SPI5CONINV      PIC32_R(0x2180c)
+#define SPI5STAT        PIC32_R(0x21810) /* Status */
+#define SPI5STATCLR     PIC32_R(0x21814)
+#define SPI5STATSET     PIC32_R(0x21818)
+#define SPI5STATINV     PIC32_R(0x2181c)
+#define SPI5BUF         PIC32_R(0x21820) /* Transmit and receive buffer */
+#define SPI5BRG         PIC32_R(0x21830) /* Baud rate generator */
+#define SPI5BRGCLR      PIC32_R(0x21834)
+#define SPI5BRGSET      PIC32_R(0x21838)
+#define SPI5BRGINV      PIC32_R(0x2183c)
+#define SPI5CON2        PIC32_R(0x21840) /* Control 2 */
+#define SPI5CON2CLR     PIC32_R(0x21844)
+#define SPI5CON2SET     PIC32_R(0x21848)
+#define SPI5CON2INV     PIC32_R(0x2184c)
+
+#define SPI6CON         PIC32_R(0x21a00) /* Control */
+#define SPI6CONCLR      PIC32_R(0x21a04)
+#define SPI6CONSET      PIC32_R(0x21a08)
+#define SPI6CONINV      PIC32_R(0x21a0c)
+#define SPI6STAT        PIC32_R(0x21a10) /* Status */
+#define SPI6STATCLR     PIC32_R(0x21a14)
+#define SPI6STATSET     PIC32_R(0x21a18)
+#define SPI6STATINV     PIC32_R(0x21a1c)
+#define SPI6BUF         PIC32_R(0x21a20) /* Transmit and receive buffer */
+#define SPI6BRG         PIC32_R(0x21a30) /* Baud rate generator */
+#define SPI6BRGCLR      PIC32_R(0x21a34)
+#define SPI6BRGSET      PIC32_R(0x21a38)
+#define SPI6BRGINV      PIC32_R(0x21a3c)
+#define SPI6CON2        PIC32_R(0x21a40) /* Control 2 */
+#define SPI6CON2CLR     PIC32_R(0x21a44)
+#define SPI6CON2SET     PIC32_R(0x21a48)
+#define SPI6CON2INV     PIC32_R(0x21a4c)
+
+/*
+ * SPI Control register.
+ */
+#define PIC32_SPICON_MSTEN      0x00000020 /* Master mode */
+#define PIC32_SPICON_CKP        0x00000040 /* Idle clock is high level */
+#define PIC32_SPICON_SSEN       0x00000080 /* Slave mode: SSx pin enable */
+#define PIC32_SPICON_CKE        0x00000100 /* Output data changes on
+                                            * transition from active clock
+                                            * state to Idle clock state */
+#define PIC32_SPICON_SMP        0x00000200 /* Master mode: input data sampled
+                                            * at end of data output time. */
+#define PIC32_SPICON_MODE16     0x00000400 /* 16-bit data width */
+#define PIC32_SPICON_MODE32     0x00000800 /* 32-bit data width */
+#define PIC32_SPICON_DISSDO     0x00001000 /* SDOx pin is not used */
+#define PIC32_SPICON_SIDL       0x00002000 /* Stop in Idle mode */
+#define PIC32_SPICON_FRZ        0x00004000 /* Freeze in Debug mode */
+#define PIC32_SPICON_ON         0x00008000 /* SPI Peripheral is enabled */
+#define PIC32_SPICON_ENHBUF     0x00010000 /* Enhanced buffer enable */
+#define PIC32_SPICON_SPIFE      0x00020000 /* Frame synchronization pulse
+                                            * is the first bit clock */
+#define PIC32_SPICON_FRMPOL     0x20000000 /* Frame pulse is active-high */
+#define PIC32_SPICON_FRMSYNC    0x40000000 /* Frame sync pulse input */
+#define PIC32_SPICON_FRMEN      0x80000000 /* Framed SPI support */
+
+/*
+ * SPI Status register.
+ */
+#define PIC32_SPISTAT_SPIRBF    0x00000001 /* Receive buffer is full */
+#define PIC32_SPISTAT_SPITBF    0x00000002 /* Transmit buffer is full */
+#define PIC32_SPISTAT_SPITBE    0x00000008 /* Transmit buffer is empty */
+#define PIC32_SPISTAT_SPIRBE    0x00000020 /* Receive buffer is empty */
+#define PIC32_SPISTAT_SPIROV    0x00000040 /* Receive overflow flag */
+#define PIC32_SPISTAT_SPIBUSY   0x00000800 /* SPI is busy */
+
+/*--------------------------------------
+ * USB registers.
+ */
+#define USBCSR0         PIC32_R(0xE3000)   /*  */
+#define USBCSR1         PIC32_R(0xE3004)
+#define USBCSR2         PIC32_R(0xE3008)
+#define USBCSR3         PIC32_R(0xE300C)
+#define USBIENCSR0      PIC32_R(0xE3010)   /*  */
+#define USBIENCSR1      PIC32_R(0xE3014)
+#define USBIENCSR2      PIC32_R(0xE3018)
+#define USBIENCSR3      PIC32_R(0xE301C)
+#define USBFIFO0        PIC32_R(0xE3020)   /*  */
+#define USBFIFO1        PIC32_R(0xE3024)
+#define USBFIFO2        PIC32_R(0xE3028)
+#define USBFIFO3        PIC32_R(0xE302C)
+#define USBFIFO4        PIC32_R(0xE3030)
+#define USBFIFO5        PIC32_R(0xE3034)
+#define USBFIFO6        PIC32_R(0xE3038)
+#define USBFIFO7        PIC32_R(0xE303C)
+#define USBOTG          PIC32_R(0xE3060)   /*  */
+#define USBFIFOA        PIC32_R(0xE3064)   /*  */
+#define USBHWVER        PIC32_R(0xE306C)   /*  */
+#define USBINFO         PIC32_R(0xE3078)   /*  */
+#define USBEOFRST       PIC32_R(0xE307C)   /*  */
+#define USBE0TXA        PIC32_R(0xE3080)   /*  */
+#define USBE0RXA        PIC32_R(0xE3084)   /*  */
+#define USBE1TXA        PIC32_R(0xE3088)
+#define USBE1RXA        PIC32_R(0xE308C)
+#define USBE2TXA        PIC32_R(0xE3090)
+#define USBE2RXA        PIC32_R(0xE3094)
+#define USBE3TXA        PIC32_R(0xE3098)
+#define USBE3RXA        PIC32_R(0xE309C)
+#define USBE4TXA        PIC32_R(0xE30A0)
+#define USBE4RXA        PIC32_R(0xE30A4)
+#define USBE5TXA        PIC32_R(0xE30A8)
+#define USBE5RXA        PIC32_R(0xE30AC)
+#define USBE6TXA        PIC32_R(0xE30B0)
+#define USBE6RXA        PIC32_R(0xE30B4)
+#define USBE7TXA        PIC32_R(0xE30B8)
+#define USBE7RXA        PIC32_R(0xE30BC)
+#define USBE0CSR0       PIC32_R(0xE3100)   /*  */
+#define USBE0CSR2       PIC32_R(0xE3108)
+#define USBE0CSR3       PIC32_R(0xE310C)
+#define USBE1CSR0       PIC32_R(0xE3110)
+#define USBE1CSR1       PIC32_R(0xE3114)
+#define USBE1CSR2       PIC32_R(0xE3118)
+#define USBE1CSR3       PIC32_R(0xE311C)
+#define USBE2CSR0       PIC32_R(0xE3120)
+#define USBE2CSR1       PIC32_R(0xE3124)
+#define USBE2CSR2       PIC32_R(0xE3128)
+#define USBE2CSR3       PIC32_R(0xE312C)
+#define USBE3CSR0       PIC32_R(0xE3130)
+#define USBE3CSR1       PIC32_R(0xE3134)
+#define USBE3CSR2       PIC32_R(0xE3138)
+#define USBE3CSR3       PIC32_R(0xE313C)
+#define USBE4CSR0       PIC32_R(0xE3140)
+#define USBE4CSR1       PIC32_R(0xE3144)
+#define USBE4CSR2       PIC32_R(0xE3148)
+#define USBE4CSR3       PIC32_R(0xE314C)
+#define USBE5CSR0       PIC32_R(0xE3150)
+#define USBE5CSR1       PIC32_R(0xE3154)
+#define USBE5CSR2       PIC32_R(0xE3158)
+#define USBE5CSR3       PIC32_R(0xE315C)
+#define USBE6CSR0       PIC32_R(0xE3160)
+#define USBE6CSR1       PIC32_R(0xE3164)
+#define USBE6CSR2       PIC32_R(0xE3168)
+#define USBE6CSR3       PIC32_R(0xE316C)
+#define USBE7CSR0       PIC32_R(0xE3170)
+#define USBE7CSR1       PIC32_R(0xE3174)
+#define USBE7CSR2       PIC32_R(0xE3178)
+#define USBE7CSR3       PIC32_R(0xE317C)
+#define USBDMAINT       PIC32_R(0xE3200)   /*  */
+#define USBDMA1C        PIC32_R(0xE3204)   /*  */
+#define USBDMA1A        PIC32_R(0xE3208)   /*  */
+#define USBDMA1N        PIC32_R(0xE320C)   /*  */
+#define USBDMA2C        PIC32_R(0xE3214)
+#define USBDMA2A        PIC32_R(0xE3218)
+#define USBDMA2N        PIC32_R(0xE321C)
+#define USBDMA3C        PIC32_R(0xE3224)
+#define USBDMA3A        PIC32_R(0xE3228)
+#define USBDMA3N        PIC32_R(0xE322C)
+#define USBDMA4C        PIC32_R(0xE3234)
+#define USBDMA4A        PIC32_R(0xE3238)
+#define USBDMA4N        PIC32_R(0xE323C)
+#define USBDMA5C        PIC32_R(0xE3244)
+#define USBDMA5A        PIC32_R(0xE3248)
+#define USBDMA5N        PIC32_R(0xE324C)
+#define USBDMA6C        PIC32_R(0xE3254)
+#define USBDMA6A        PIC32_R(0xE3258)
+#define USBDMA6N        PIC32_R(0xE325C)
+#define USBDMA7C        PIC32_R(0xE3264)
+#define USBDMA7A        PIC32_R(0xE3268)
+#define USBDMA7N        PIC32_R(0xE326C)
+#define USBDMA8C        PIC32_R(0xE3274)
+#define USBDMA8A        PIC32_R(0xE3278)
+#define USBDMA8N        PIC32_R(0xE327C)
+#define USBE1RPC        PIC32_R(0xE3304)   /*  */
+#define USBE2RPC        PIC32_R(0xE3308)
+#define USBE3RPC        PIC32_R(0xE330C)
+#define USBE4RPC        PIC32_R(0xE3310)
+#define USBE5RPC        PIC32_R(0xE3314)
+#define USBE6RPC        PIC32_R(0xE3318)
+#define USBE7RPC        PIC32_R(0xE331C)
+#define USBDPBFD        PIC32_R(0xE3340)   /*  */
+#define USBTMCON1       PIC32_R(0xE3344)   /*  */
+#define USBTMCON2       PIC32_R(0xE3348)   /*  */
+#define USBLPMR1        PIC32_R(0xE3360)   /*  */
+#define USBLMPR2        PIC32_R(0xE3364)   /*  */
+
+/*--------------------------------------
+ * Ethernet registers.
+ */
+#define ETHCON1         PIC32_R(0x82000) /* Control 1 */
+#define ETHCON1CLR      PIC32_R(0x82004)
+#define ETHCON1SET      PIC32_R(0x82008)
+#define ETHCON1INV      PIC32_R(0x8200c)
+#define ETHCON2         PIC32_R(0x82010) /* Control 2: RX data buffer size */
+#define ETHTXST         PIC32_R(0x82020) /* Tx descriptor start address */
+#define ETHRXST         PIC32_R(0x82030) /* Rx descriptor start address */
+#define ETHHT0          PIC32_R(0x82040) /* Hash tasble 0 */
+#define ETHHT1          PIC32_R(0x82050) /* Hash tasble 1 */
+#define ETHPMM0         PIC32_R(0x82060) /* Pattern match mask 0 */
+#define ETHPMM1         PIC32_R(0x82070) /* Pattern match mask 1 */
+#define ETHPMCS         PIC32_R(0x82080) /* Pattern match checksum */
+#define ETHPMO          PIC32_R(0x82090) /* Pattern match offset */
+#define ETHRXFC         PIC32_R(0x820a0) /* Receive filter configuration */
+#define ETHRXWM         PIC32_R(0x820b0) /* Receive watermarks */
+#define ETHIEN          PIC32_R(0x820c0) /* Interrupt enable */
+#define ETHIENCLR       PIC32_R(0x820c4)
+#define ETHIENSET       PIC32_R(0x820c8)
+#define ETHIENINV       PIC32_R(0x820cc)
+#define ETHIRQ          PIC32_R(0x820d0) /* Interrupt request */
+#define ETHIRQCLR       PIC32_R(0x820d4)
+#define ETHIRQSET       PIC32_R(0x820d8)
+#define ETHIRQINV       PIC32_R(0x820dc)
+#define ETHSTAT         PIC32_R(0x820e0) /* Status */
+#define ETHRXOVFLOW     PIC32_R(0x82100) /* Receive overflow statistics */
+#define ETHFRMTXOK      PIC32_R(0x82110) /* Frames transmitted OK statistics */
+#define ETHSCOLFRM      PIC32_R(0x82120) /* Single collision statistics */
+#define ETHMCOLFRM      PIC32_R(0x82130) /* Multiple collision statistics */
+#define ETHFRMRXOK      PIC32_R(0x82140) /* Frames received OK statistics */
+#define ETHFCSERR       PIC32_R(0x82150) /* Frame check error statistics */
+#define ETHALGNERR      PIC32_R(0x82160) /* Alignment errors statistics */
+#define EMAC1CFG1       PIC32_R(0x82200) /* MAC configuration 1 */
+#define EMAC1CFG2       PIC32_R(0x82210) /* MAC configuration 2 */
+#define EMAC1CFG2CLR    PIC32_R(0x82214)
+#define EMAC1CFG2SET    PIC32_R(0x82218)
+#define EMAC1CFG2INV    PIC32_R(0x8221c)
+#define EMAC1IPGT       PIC32_R(0x82220) /* MAC back-to-back interpacket gap */
+#define EMAC1IPGR       PIC32_R(0x82230) /* MAC non-back-to-back gap */
+#define EMAC1CLRT       PIC32_R(0x82240) /* MAC collision window/retry limit */
+#define EMAC1MAXF       PIC32_R(0x82250) /* MAC maximum frame length */
+#define EMAC1SUPP       PIC32_R(0x82260) /* MAC PHY support */
+#define EMAC1SUPPCLR    PIC32_R(0x82264)
+#define EMAC1SUPPSET    PIC32_R(0x82268)
+#define EMAC1SUPPINV    PIC32_R(0x8226c)
+#define EMAC1TEST       PIC32_R(0x82270) /* MAC test */
+#define EMAC1MCFG       PIC32_R(0x82280) /* MII configuration */
+#define EMAC1MCMD       PIC32_R(0x82290) /* MII command */
+#define EMAC1MCMDCLR    PIC32_R(0x82294)
+#define EMAC1MCMDSET    PIC32_R(0x82298)
+#define EMAC1MCMDINV    PIC32_R(0x8229c)
+#define EMAC1MADR       PIC32_R(0x822a0) /* MII address */
+#define EMAC1MWTD       PIC32_R(0x822b0) /* MII write data */
+#define EMAC1MRDD       PIC32_R(0x822c0) /* MII read data */
+#define EMAC1MIND       PIC32_R(0x822d0) /* MII indicators */
+#define EMAC1SA0        PIC32_R(0x82300) /* MAC station address 0 */
+#define EMAC1SA1        PIC32_R(0x82310) /* MAC station address 1 */
+#define EMAC1SA2        PIC32_R(0x82320) /* MAC station address 2 */
+
+/*
+ * Ethernet Control register 1.
+ */
+#define PIC32_ETHCON1_PTV(n)    ((n)<<16)   /* Pause timer value */
+#define PIC32_ETHCON1_ON            0x8000  /* Ethernet module enabled */
+#define PIC32_ETHCON1_SIDL          0x2000  /* Stop in idle mode */
+#define PIC32_ETHCON1_TXRTS         0x0200  /* Transmit request to send */
+#define PIC32_ETHCON1_RXEN          0x0100  /* Receive enable */
+#define PIC32_ETHCON1_AUTOFC        0x0080  /* Automatic flow control */
+#define PIC32_ETHCON1_MANFC         0x0010  /* Manual flow control */
+#define PIC32_ETHCON1_BUFCDEC       0x0001  /* Desc.buffer count decrement */
+
+/*
+ * Ethernet Receive Filter Configuration register.
+ */
+#define PIC32_ETHRXFC_HTEN          0x8000  /* Enable hash table filtering */
+#define PIC32_ETHRXFC_MPEN          0x4000  /* Enable Magic Packet filtering */
+#define PIC32_ETHRXFC_NOTPM         0x1000  /* Pattern match inversion */
+#define PIC32_ETHRXFC_PMMODE_MAGIC  0x0900  /* Packet = magic */
+#define PIC32_ETHRXFC_PMMODE_HT     0x0800  /* Hash table filter match */
+#define PIC32_ETHRXFC_PMMODE_BCAST  0x0600  /* Destination = broadcast */
+#define PIC32_ETHRXFC_PMMODE_UCAST  0x0400  /* Destination = unicast address */
+#define PIC32_ETHRXFC_PMMODE_STN    0x0200  /* Destination = station address */
+#define PIC32_ETHRXFC_PMMODE_CSUM   0x0100  /* Successful if checksum matches */
+#define PIC32_ETHRXFC_CRCERREN      0x0080  /* CRC error collection enable */
+#define PIC32_ETHRXFC_CRCOKEN       0x0040  /* CRC OK enable */
+#define PIC32_ETHRXFC_RUNTERREN     0x0020  /* Runt error collection enable */
+#define PIC32_ETHRXFC_RUNTEN        0x0010  /* Runt filter enable */
+#define PIC32_ETHRXFC_UCEN          0x0008  /* Unicast filter enable */
+#define PIC32_ETHRXFC_NOTMEEN       0x0004  /* Not Me unicast enable */
+#define PIC32_ETHRXFC_MCEN          0x0002  /* Multicast filter enable */
+#define PIC32_ETHRXFC_BCEN          0x0001  /* Broadcast filter enable */
+
+/*
+ * Ethernet Receive Watermarks register.
+ */
+#define PIC32_ETHRXWM_FWM(n)    ((n)<<16)   /* Receive Full Watermark */
+#define PIC32_ETHRXWM_EWM(n)    (n)         /* Receive Empty Watermark */
+
+/*
+ * Ethernet Interrupt Request register.
+ */
+#define PIC32_ETHIRQ_TXBUSE         0x4000  /* Transmit Bus Error */
+#define PIC32_ETHIRQ_RXBUSE         0x2000  /* Receive Bus Error */
+#define PIC32_ETHIRQ_EWMARK         0x0200  /* Empty Watermark */
+#define PIC32_ETHIRQ_FWMARK         0x0100  /* Full Watermark */
+#define PIC32_ETHIRQ_RXDONE         0x0080  /* Receive Done */
+#define PIC32_ETHIRQ_PKTPEND        0x0040  /* Packet Pending */
+#define PIC32_ETHIRQ_RXACT          0x0020  /* Receive Activity */
+#define PIC32_ETHIRQ_TXDONE         0x0008  /* Transmit Done */
+#define PIC32_ETHIRQ_TXABORT        0x0004  /* Transmitter Abort */
+#define PIC32_ETHIRQ_RXBUFNA        0x0002  /* Receive Buffer Not Available */
+#define PIC32_ETHIRQ_RXOVFLW        0x0001  /* Receive FIFO Overflow */
+
+/*
+ * Ethernet Status register.
+ */
+#define PIC32_ETHSTAT_BUFCNT    0x00ff0000  /* Packet buffer count */
+#define PIC32_ETHSTAT_ETHBUSY       0x0080  /* Ethernet logic is busy */
+#define PIC32_ETHSTAT_TXBUSY        0x0040  /* TX logic is receiving data */
+#define PIC32_ETHSTAT_RXBUSY        0x0020  /* RX logic is receiving data */
+
+/*
+ * Ethernet MAC configuration register 1.
+ */
+#define PIC32_EMAC1CFG1_SOFTRESET   0x8000  /* Soft reset */
+#define PIC32_EMAC1CFG1_SIMRESET    0x4000  /* Reset TX random generator */
+#define PIC32_EMAC1CFG1_RESETRMCS   0x0800  /* Reset MCS/RX logic */
+#define PIC32_EMAC1CFG1_RESETRFUN   0x0400  /* Reset RX function */
+#define PIC32_EMAC1CFG1_RESETTMCS   0x0200  /* Reset MCS/TX logic */
+#define PIC32_EMAC1CFG1_RESETTFUN   0x0100  /* Reset TX function */
+#define PIC32_EMAC1CFG1_LOOPBACK    0x0010  /* MAC Loopback mode */
+#define PIC32_EMAC1CFG1_TXPAUSE     0x0008  /* MAC TX flow control */
+#define PIC32_EMAC1CFG1_RXPAUSE     0x0004  /* MAC RX flow control */
+#define PIC32_EMAC1CFG1_PASSALL     0x0002  /* MAC accept ctl frames as well */
+#define PIC32_EMAC1CFG1_RXENABLE    0x0001  /* MAC Receive Enable */
+
+/*
+ * Ethernet MAC configuration register 2.
+ */
+#define PIC32_EMAC1CFG2_EXCESSDFR   0x4000  /* Defer to carrier indefinitely */
+#define PIC32_EMAC1CFG2_BPNOBKOFF   0x2000  /* Backpressure/No Backoff */
+#define PIC32_EMAC1CFG2_NOBKOFF     0x1000  /* No Backoff */
+#define PIC32_EMAC1CFG2_LONGPRE     0x0200  /* Long preamble enforcement */
+#define PIC32_EMAC1CFG2_PUREPRE     0x0100  /* Pure preamble enforcement */
+#define PIC32_EMAC1CFG2_AUTOPAD     0x0080  /* Automatic detect pad enable */
+#define PIC32_EMAC1CFG2_VLANPAD     0x0040  /* VLAN pad enable */
+#define PIC32_EMAC1CFG2_PADENABLE   0x0020  /* Pad/CRC enable */
+#define PIC32_EMAC1CFG2_CRCENABLE   0x0010  /* CRC enable */
+#define PIC32_EMAC1CFG2_DELAYCRC    0x0008  /* Delayed CRC */
+#define PIC32_EMAC1CFG2_HUGEFRM     0x0004  /* Huge frame enable */
+#define PIC32_EMAC1CFG2_LENGTHCK    0x0002  /* Frame length checking */
+#define PIC32_EMAC1CFG2_FULLDPLX    0x0001  /* Full-duplex operation */
+
+/*
+ * Ethernet MAC non-back-to-back interpacket gap register.
+ */
+#define PIC32_EMAC1IPGR(p1, p2)     ((p1)<<8 | (p2))
+
+/*
+ * Ethernet MAC collision window/retry limit register.
+ */
+#define PIC32_EMAC1CLRT(w, r)       ((w)<<8 | (r))
+
+/*
+ * Ethernet PHY support register.
+ */
+#define PIC32_EMAC1SUPP_RESETRMII   0x0800  /* Reset the RMII module */
+#define PIC32_EMAC1SUPP_SPEEDRMII   0x0100  /* RMII speed:
+                                             * 1=100Mbps, 0=10Mbps */
+
+/*
+ * Ethernet MAC test register.
+ */
+#define PIC32_EMAC1TEST_TESTBP      0x0004  /* Test backpressure */
+#define PIC32_EMAC1TEST_TESTPAUSE   0x0002  /* Test pause */
+#define PIC32_EMAC1TEST_SHRTQNTA    0x0001  /* Shortcut pause quanta */
+
+/*
+ * Ethernet MII configuration register.
+ */
+#define PIC32_EMAC1MCFG_RESETMGMT   0x8000  /* Reset the MII module */
+#define PIC32_EMAC1MCFG_CLKSEL_4    0x0000  /* Clock divide by 4 */
+#define PIC32_EMAC1MCFG_CLKSEL_6    0x0008  /* Clock divide by 6 */
+#define PIC32_EMAC1MCFG_CLKSEL_8    0x000c  /* Clock divide by 8 */
+#define PIC32_EMAC1MCFG_CLKSEL_10   0x0010  /* Clock divide by 10 */
+#define PIC32_EMAC1MCFG_CLKSEL_14   0x0014  /* Clock divide by 14 */
+#define PIC32_EMAC1MCFG_CLKSEL_20   0x0018  /* Clock divide by 20 */
+#define PIC32_EMAC1MCFG_CLKSEL_28   0x001c  /* Clock divide by 28 */
+#define PIC32_EMAC1MCFG_CLKSEL_40   0x0020  /* Clock divide by 40 */
+#define PIC32_EMAC1MCFG_CLKSEL_48   0x0024  /* Clock divide by 48 */
+#define PIC32_EMAC1MCFG_CLKSEL_50   0x0028  /* Clock divide by 50 */
+#define PIC32_EMAC1MCFG_NOPRE       0x0002  /* Suppress preamble */
+#define PIC32_EMAC1MCFG_SCANINC     0x0001  /* Scan increment */
+
+/*
+ * Ethernet MII command register.
+ */
+#define PIC32_EMAC1MCMD_SCAN        0x0002  /* Continuous scan mode */
+#define PIC32_EMAC1MCMD_READ        0x0001  /* Single read cycle */
+
+/*
+ * Ethernet MII address register.
+ */
+#define PIC32_EMAC1MADR(p, r)       ((p)<<8 | (r))
+
+/*
+ * Ethernet MII indicators register.
+ */
+#define PIC32_EMAC1MIND_LINKFAIL    0x0008  /* Link fail */
+#define PIC32_EMAC1MIND_NOTVALID    0x0004  /* Read data not valid */
+#define PIC32_EMAC1MIND_SCAN        0x0002  /* Scanning in progress */
+#define PIC32_EMAC1MIND_MIIMBUSY    0x0001  /* Read/write cycle in progress */
+
+/*--------------------------------------
+ * Interrupt controller registers.
+ */
+#define INTCON          PIC32_R(0x10000)       /* Interrupt Control */
+#define INTCONCLR       PIC32_R(0x10004)
+#define INTCONSET       PIC32_R(0x10008)
+#define INTCONINV       PIC32_R(0x1000C)
+#define PRISS           PIC32_R(0x10010)       /* Priority Shadow Select */
+#define PRISSCLR        PIC32_R(0x10014)
+#define PRISSSET        PIC32_R(0x10018)
+#define PRISSINV        PIC32_R(0x1001C)
+#define INTSTAT         PIC32_R(0x10020)       /* Interrupt Status */
+#define IPTMR           PIC32_R(0x10030)       /* Temporal Proximity Timer */
+#define IPTMRCLR        PIC32_R(0x10034)
+#define IPTMRSET        PIC32_R(0x10038)
+#define IPTMRINV        PIC32_R(0x1003C)
+/* IFS(0..5) - Interrupt Flag Status */
+#define IFS(n)          PIC32_R(0x10040+((n)<<4))
+#define IFSCLR(n)       PIC32_R(0x10044+((n)<<4))
+#define IFSSET(n)       PIC32_R(0x10048+((n)<<4))
+#define IFSINV(n)       PIC32_R(0x1004C+((n)<<4))
+#define IFS0            IFS(0)
+#define IFS1            IFS(1)
+#define IFS2            IFS(2)
+#define IFS3            IFS(3)
+#define IFS4            IFS(4)
+#define IFS5            IFS(5)
+/* IEC(0..5) - Interrupt Enable Control */
+#define IEC(n)          PIC32_R(0x100c0+((n)<<4))
+#define IECCLR(n)       PIC32_R(0x100c4+((n)<<4))
+#define IECSET(n)       PIC32_R(0x100c8+((n)<<4))
+#define IECINV(n)       PIC32_R(0x100cC+((n)<<4))
+#define IEC0            IEC(0)
+#define IEC1            IEC(1)
+#define IEC2            IEC(2)
+#define IEC3            IEC(3)
+#define IEC4            IEC(4)
+#define IEC5            IEC(5)
+/* IPC(0..47) - Interrupt Priority Control */
+#define IPC(n)          PIC32_R(0x10140+((n)<<4))
+#define IPCCLR(n)       PIC32_R(0x10144+((n)<<4))
+#define IPCSET(n)       PIC32_R(0x10148+((n)<<4))
+#define IPCINV(n)       PIC32_R(0x1014C+((n)<<4))
+#define IPC0            IPC(0)
+#define IPC1            IPC(1)
+#define IPC2            IPC(2)
+#define IPC3            IPC(3)
+#define IPC4            IPC(4)
+#define IPC5            IPC(5)
+#define IPC6            IPC(6)
+#define IPC7            IPC(7)
+#define IPC8            IPC(8)
+#define IPC9            IPC(9)
+#define IPC10           IPC(10)
+#define IPC11           IPC(11)
+#define IPC12           IPC(12)
+#define IPC13           IPC(13)
+#define IPC14           IPC(14)
+#define IPC15           IPC(15)
+#define IPC16           IPC(16)
+#define IPC17           IPC(17)
+#define IPC18           IPC(18)
+#define IPC19           IPC(19)
+#define IPC20           IPC(20)
+#define IPC21           IPC(21)
+#define IPC22           IPC(22)
+#define IPC23           IPC(23)
+#define IPC24           IPC(24)
+#define IPC25           IPC(25)
+#define IPC26           IPC(26)
+#define IPC27           IPC(27)
+#define IPC28           IPC(28)
+#define IPC29           IPC(29)
+#define IPC30           IPC(30)
+#define IPC31           IPC(31)
+#define IPC32           IPC(32)
+#define IPC33           IPC(33)
+#define IPC34           IPC(34)
+#define IPC35           IPC(35)
+#define IPC36           IPC(36)
+#define IPC37           IPC(37)
+#define IPC38           IPC(38)
+#define IPC39           IPC(39)
+#define IPC40           IPC(40)
+#define IPC41           IPC(41)
+#define IPC42           IPC(42)
+#define IPC43           IPC(43)
+#define IPC44           IPC(44)
+#define IPC45           IPC(45)
+#define IPC46           IPC(46)
+#define IPC47           IPC(47)
+/* OFF(0..190) - Interrupt Vector Address Offset */
+#define OFF(n)          PIC32_R(0x10540+((n)<<2))
+
+/*
+ * Interrupt Control register.
+ */
+#define PIC32_INTCON_INT0EP     0x00000001  /* Rising edge polarity for
+                                             * external interrupt 0 */
+#define PIC32_INTCON_INT1EP     0x00000002  /* Rising edge polarity for int1 */
+#define PIC32_INTCON_INT2EP     0x00000004  /* Rising edge polarity for int2 */
+#define PIC32_INTCON_INT3EP     0x00000008  /* Rising edge polarity for int3 */
+#define PIC32_INTCON_INT4EP     0x00000010  /* Rising edge polarity for int4 */
+#define PIC32_INTCON_TPC(x)     ((x)<<8)    /* Temporal proximity group prio */
+#define PIC32_INTCON_MVEC       0x00001000  /* Multi-vectored mode */
+#define PIC32_INTCON_SS0        0x00010000  /* Single vector has
+                                             * a shadow register set */
+#define PIC32_INTCON_VS(x)      ((x)<<16)   /* Temporal proximity
+                                             * group priority */
+
+/*
+ * Interrupt Status register.
+ */
+#define PIC32_INTSTAT_VEC(s)    ((s) & 0xff)    /* Interrupt vector */
+#define PIC32_INTSTAT_SRIPL(s)  ((s) >> 8 & 7)  /* Requested priority level */
+#define PIC32_INTSTAT_SRIPL_MASK 0x0700
+
+/*
+ * Interrupt Prority Control register.
+ */
+/* Priority */
+#define PIC32_IPC_IP(a, b, c, d)    ((a)<<2 | (b)<<10 | (c)<<18 | (d)<<26)
+/* Subpriority */
+#define PIC32_IPC_IS(a, b, c, d)    ((a) | (b)<<8 | (c)<<16 | (d)<<24)
+
+/*
+ * IRQ numbers for PIC32MZ
+ */
+#define PIC32_IRQ_CT        0   /* Core Timer Interrupt */
+#define PIC32_IRQ_CS0       1   /* Core Software Interrupt 0 */
+#define PIC32_IRQ_CS1       2   /* Core Software Interrupt 1 */
+#define PIC32_IRQ_INT0      3   /* External Interrupt 0 */
+#define PIC32_IRQ_T1        4   /* Timer1 */
+#define PIC32_IRQ_IC1E      5   /* Input Capture 1 Error */
+#define PIC32_IRQ_IC1       6   /* Input Capture 1 */
+#define PIC32_IRQ_OC1       7   /* Output Compare 1 */
+#define PIC32_IRQ_INT1      8   /* External Interrupt 1 */
+#define PIC32_IRQ_T2        9   /* Timer2 */
+#define PIC32_IRQ_IC2E      10  /* Input Capture 2 Error */
+#define PIC32_IRQ_IC2       11  /* Input Capture 2 */
+#define PIC32_IRQ_OC2       12  /* Output Compare 2 */
+#define PIC32_IRQ_INT2      13  /* External Interrupt 2 */
+#define PIC32_IRQ_T3        14  /* Timer3 */
+#define PIC32_IRQ_IC3E      15  /* Input Capture 3 Error */
+#define PIC32_IRQ_IC3       16  /* Input Capture 3 */
+#define PIC32_IRQ_OC3       17  /* Output Compare 3 */
+#define PIC32_IRQ_INT3      18  /* External Interrupt 3 */
+#define PIC32_IRQ_T4        19  /* Timer4 */
+#define PIC32_IRQ_IC4E      20  /* Input Capture 4 Error */
+#define PIC32_IRQ_IC4       21  /* Input Capture 4 */
+#define PIC32_IRQ_OC4       22  /* Output Compare 4 */
+#define PIC32_IRQ_INT4      23  /* External Interrupt 4 */
+#define PIC32_IRQ_T5        24  /* Timer5 */
+#define PIC32_IRQ_IC5E      25  /* Input Capture 5 Error */
+#define PIC32_IRQ_IC5       26  /* Input Capture 5 */
+#define PIC32_IRQ_OC5       27  /* Output Compare 5 */
+#define PIC32_IRQ_T6        28  /* Timer6 */
+#define PIC32_IRQ_IC6E      29  /* Input Capture 6 Error */
+#define PIC32_IRQ_IC6       30  /* Input Capture 6 */
+#define PIC32_IRQ_OC6       31  /* Output Compare 6 */
+#define PIC32_IRQ_T7        32  /* Timer7 */
+#define PIC32_IRQ_IC7E      33  /* Input Capture 7 Error */
+#define PIC32_IRQ_IC7       34  /* Input Capture 7 */
+#define PIC32_IRQ_OC7       35  /* Output Compare 7 */
+#define PIC32_IRQ_T8        36  /* Timer8 */
+#define PIC32_IRQ_IC8E      37  /* Input Capture 8 Error */
+#define PIC32_IRQ_IC8       38  /* Input Capture 8 */
+#define PIC32_IRQ_OC8       39  /* Output Compare 8 */
+#define PIC32_IRQ_T9        40  /* Timer9 */
+#define PIC32_IRQ_IC9E      41  /* Input Capture 9 Error */
+#define PIC32_IRQ_IC9       42  /* Input Capture 9 */
+#define PIC32_IRQ_OC9       43  /* Output Compare 9 */
+#define PIC32_IRQ_AD1       44  /* ADC1 Global Interrupt */
+                         /* 45  -- Reserved */
+#define PIC32_IRQ_AD1DC1    46  /* ADC1 Digital Comparator 1 */
+#define PIC32_IRQ_AD1DC2    47  /* ADC1 Digital Comparator 2 */
+#define PIC32_IRQ_AD1DC3    48  /* ADC1 Digital Comparator 3 */
+#define PIC32_IRQ_AD1DC4    49  /* ADC1 Digital Comparator 4 */
+#define PIC32_IRQ_AD1DC5    50  /* ADC1 Digital Comparator 5 */
+#define PIC32_IRQ_AD1DC6    51  /* ADC1 Digital Comparator 6 */
+#define PIC32_IRQ_AD1DF1    52  /* ADC1 Digital Filter 1 */
+#define PIC32_IRQ_AD1DF2    53  /* ADC1 Digital Filter 2 */
+#define PIC32_IRQ_AD1DF3    54  /* ADC1 Digital Filter 3 */
+#define PIC32_IRQ_AD1DF4    55  /* ADC1 Digital Filter 4 */
+#define PIC32_IRQ_AD1DF5    56  /* ADC1 Digital Filter 5 */
+#define PIC32_IRQ_AD1DF6    57  /* ADC1 Digital Filter 6 */
+                         /* 58  -- Reserved */
+#define PIC32_IRQ_AD1D0     59  /* ADC1 Data 0 */
+#define PIC32_IRQ_AD1D1     60  /* ADC1 Data 1 */
+#define PIC32_IRQ_AD1D2     61  /* ADC1 Data 2 */
+#define PIC32_IRQ_AD1D3     62  /* ADC1 Data 3 */
+#define PIC32_IRQ_AD1D4     63  /* ADC1 Data 4 */
+#define PIC32_IRQ_AD1D5     64  /* ADC1 Data 5 */
+#define PIC32_IRQ_AD1D6     65  /* ADC1 Data 6 */
+#define PIC32_IRQ_AD1D7     66  /* ADC1 Data 7 */
+#define PIC32_IRQ_AD1D8     67  /* ADC1 Data 8 */
+#define PIC32_IRQ_AD1D9     68  /* ADC1 Data 9 */
+#define PIC32_IRQ_AD1D10    69  /* ADC1 Data 10 */
+#define PIC32_IRQ_AD1D11    70  /* ADC1 Data 11 */
+#define PIC32_IRQ_AD1D12    71  /* ADC1 Data 12 */
+#define PIC32_IRQ_AD1D13    72  /* ADC1 Data 13 */
+#define PIC32_IRQ_AD1D14    73  /* ADC1 Data 14 */
+#define PIC32_IRQ_AD1D15    74  /* ADC1 Data 15 */
+#define PIC32_IRQ_AD1D16    75  /* ADC1 Data 16 */
+#define PIC32_IRQ_AD1D17    76  /* ADC1 Data 17 */
+#define PIC32_IRQ_AD1D18    77  /* ADC1 Data 18 */
+#define PIC32_IRQ_AD1D19    78  /* ADC1 Data 19 */
+#define PIC32_IRQ_AD1D20    79  /* ADC1 Data 20 */
+#define PIC32_IRQ_AD1D21    80  /* ADC1 Data 21 */
+#define PIC32_IRQ_AD1D22    81  /* ADC1 Data 22 */
+#define PIC32_IRQ_AD1D23    82  /* ADC1 Data 23 */
+#define PIC32_IRQ_AD1D24    83  /* ADC1 Data 24 */
+#define PIC32_IRQ_AD1D25    84  /* ADC1 Data 25 */
+#define PIC32_IRQ_AD1D26    85  /* ADC1 Data 26 */
+#define PIC32_IRQ_AD1D27    86  /* ADC1 Data 27 */
+#define PIC32_IRQ_AD1D28    87  /* ADC1 Data 28 */
+#define PIC32_IRQ_AD1D29    88  /* ADC1 Data 29 */
+#define PIC32_IRQ_AD1D30    89  /* ADC1 Data 30 */
+#define PIC32_IRQ_AD1D31    90  /* ADC1 Data 31 */
+#define PIC32_IRQ_AD1D32    91  /* ADC1 Data 32 */
+#define PIC32_IRQ_AD1D33    92  /* ADC1 Data 33 */
+#define PIC32_IRQ_AD1D34    93  /* ADC1 Data 34 */
+#define PIC32_IRQ_AD1D35    94  /* ADC1 Data 35 */
+#define PIC32_IRQ_AD1D36    95  /* ADC1 Data 36 */
+#define PIC32_IRQ_AD1D37    96  /* ADC1 Data 37 */
+#define PIC32_IRQ_AD1D38    97  /* ADC1 Data 38 */
+#define PIC32_IRQ_AD1D39    98  /* ADC1 Data 39 */
+#define PIC32_IRQ_AD1D40    99  /* ADC1 Data 40 */
+#define PIC32_IRQ_AD1D41    100 /* ADC1 Data 41 */
+#define PIC32_IRQ_AD1D42    101 /* ADC1 Data 42 */
+#define PIC32_IRQ_AD1D43    102 /* ADC1 Data 43 */
+#define PIC32_IRQ_AD1D44    103 /* ADC1 Data 44 */
+#define PIC32_IRQ_CPC       104 /* Core Performance Counter */
+#define PIC32_IRQ_CFDC      105 /* Core Fast Debug Channel */
+#define PIC32_IRQ_SB        106 /* System Bus Protection Violation */
+#define PIC32_IRQ_CRPT      107 /* Crypto Engine Event */
+                         /* 108 -- Reserved */
+#define PIC32_IRQ_SPI1E     109 /* SPI1 Fault */
+#define PIC32_IRQ_SPI1RX    110 /* SPI1 Receive Done */
+#define PIC32_IRQ_SPI1TX    111 /* SPI1 Transfer Done */
+#define PIC32_IRQ_U1E       112 /* UART1 Fault */
+#define PIC32_IRQ_U1RX      113 /* UART1 Receive Done */
+#define PIC32_IRQ_U1TX      114 /* UART1 Transfer Done */
+#define PIC32_IRQ_I2C1B     115 /* I2C1 Bus Collision Event */
+#define PIC32_IRQ_I2C1S     116 /* I2C1 Slave Event */
+#define PIC32_IRQ_I2C1M     117 /* I2C1 Master Event */
+#define PIC32_IRQ_CNA       118 /* PORTA Input Change Interrupt */
+#define PIC32_IRQ_CNB       119 /* PORTB Input Change Interrupt */
+#define PIC32_IRQ_CNC       120 /* PORTC Input Change Interrupt */
+#define PIC32_IRQ_CND       121 /* PORTD Input Change Interrupt */
+#define PIC32_IRQ_CNE       122 /* PORTE Input Change Interrupt */
+#define PIC32_IRQ_CNF       123 /* PORTF Input Change Interrupt */
+#define PIC32_IRQ_CNG       124 /* PORTG Input Change Interrupt */
+#define PIC32_IRQ_CNH       125 /* PORTH Input Change Interrupt */
+#define PIC32_IRQ_CNJ       126 /* PORTJ Input Change Interrupt */
+#define PIC32_IRQ_CNK       127 /* PORTK Input Change Interrupt */
+#define PIC32_IRQ_PMP       128 /* Parallel Master Port */
+#define PIC32_IRQ_PMPE      129 /* Parallel Master Port Error */
+#define PIC32_IRQ_CMP1      130 /* Comparator 1 Interrupt */
+#define PIC32_IRQ_CMP2      131 /* Comparator 2 Interrupt */
+#define PIC32_IRQ_USB       132 /* USB General Event */
+#define PIC32_IRQ_USBDMA    133 /* USB DMA Event */
+#define PIC32_IRQ_DMA0      134 /* DMA Channel 0 */
+#define PIC32_IRQ_DMA1      135 /* DMA Channel 1 */
+#define PIC32_IRQ_DMA2      136 /* DMA Channel 2 */
+#define PIC32_IRQ_DMA3      137 /* DMA Channel 3 */
+#define PIC32_IRQ_DMA4      138 /* DMA Channel 4 */
+#define PIC32_IRQ_DMA5      139 /* DMA Channel 5 */
+#define PIC32_IRQ_DMA6      140 /* DMA Channel 6 */
+#define PIC32_IRQ_DMA7      141 /* DMA Channel 7 */
+#define PIC32_IRQ_SPI2E     142 /* SPI2 Fault */
+#define PIC32_IRQ_SPI2RX    143 /* SPI2 Receive Done */
+#define PIC32_IRQ_SPI2TX    144 /* SPI2 Transfer Done */
+#define PIC32_IRQ_U2E       145 /* UART2 Fault */
+#define PIC32_IRQ_U2RX      146 /* UART2 Receive Done */
+#define PIC32_IRQ_U2TX      147 /* UART2 Transfer Done */
+#define PIC32_IRQ_I2C2B     148 /* I2C2 Bus Collision Event */
+#define PIC32_IRQ_I2C2S     149 /* I2C2 Slave Event */
+#define PIC32_IRQ_I2C2M     150 /* I2C2 Master Event */
+#define PIC32_IRQ_CAN1      151 /* Control Area Network 1 */
+#define PIC32_IRQ_CAN2      152 /* Control Area Network 2 */
+#define PIC32_IRQ_ETH       153 /* Ethernet Interrupt */
+#define PIC32_IRQ_SPI3E     154 /* SPI3 Fault */
+#define PIC32_IRQ_SPI3RX    155 /* SPI3 Receive Done */
+#define PIC32_IRQ_SPI3TX    156 /* SPI3 Transfer Done */
+#define PIC32_IRQ_U3E       157 /* UART3 Fault */
+#define PIC32_IRQ_U3RX      158 /* UART3 Receive Done */
+#define PIC32_IRQ_U3TX      159 /* UART3 Transfer Done */
+#define PIC32_IRQ_I2C3B     160 /* I2C3 Bus Collision Event */
+#define PIC32_IRQ_I2C3S     161 /* I2C3 Slave Event */
+#define PIC32_IRQ_I2C3M     162 /* I2C3 Master Event */
+#define PIC32_IRQ_SPI4E     163 /* SPI4 Fault */
+#define PIC32_IRQ_SPI4RX    164 /* SPI4 Receive Done */
+#define PIC32_IRQ_SPI4TX    165 /* SPI4 Transfer Done */
+#define PIC32_IRQ_RTCC      166 /* Real Time Clock */
+#define PIC32_IRQ_FCE       167 /* Flash Control Event */
+#define PIC32_IRQ_PRE       168 /* Prefetch Module SEC Event */
+#define PIC32_IRQ_SQI1      169 /* SQI1 Event */
+#define PIC32_IRQ_U4E       170 /* UART4 Fault */
+#define PIC32_IRQ_U4RX      171 /* UART4 Receive Done */
+#define PIC32_IRQ_U4TX      172 /* UART4 Transfer Done */
+#define PIC32_IRQ_I2C4B     173 /* I2C4 Bus Collision Event */
+#define PIC32_IRQ_I2C4S     174 /* I2C4 Slave Event */
+#define PIC32_IRQ_I2C4M     175 /* I2C4 Master Event */
+#define PIC32_IRQ_SPI5E     176 /* SPI5 Fault */
+#define PIC32_IRQ_SPI5RX    177 /* SPI5 Receive Done */
+#define PIC32_IRQ_SPI5TX    178 /* SPI5 Transfer Done */
+#define PIC32_IRQ_U5E       179 /* UART5 Fault */
+#define PIC32_IRQ_U5RX      180 /* UART5 Receive Done */
+#define PIC32_IRQ_U5TX      181 /* UART5 Transfer Done */
+#define PIC32_IRQ_I2C5B     182 /* I2C5 Bus Collision Event */
+#define PIC32_IRQ_I2C5S     183 /* I2C5 Slave Event */
+#define PIC32_IRQ_I2C5M     184 /* I2C5 Master Event */
+#define PIC32_IRQ_SPI6E     185 /* SPI6 Fault */
+#define PIC32_IRQ_SPI6RX    186 /* SPI6 Receive Done */
+#define PIC32_IRQ_SPI6TX    187 /* SPI6 Transfer Done */
+#define PIC32_IRQ_U6E       188 /* UART6 Fault */
+#define PIC32_IRQ_U6RX      189 /* UART6 Receive Done */
+#define PIC32_IRQ_U6TX      190 /* UART6 Transfer Done */
+                         /* 191 -- Reserved */
+#define PIC32_IRQ_LAST      190 /* Last valid irq number */
+
+#endif /* _IO_PIC32MZ_H */