xtensa

Module

The xtensa architecture

Xtensa is used in the esp8266 and esp32 chips from espressif.

class ppci.arch.xtensa.XtensaArch(options=None)

Xtensa architecture implementation.

determine_arg_locations(arg_types)

Determine argument location for a given function

determine_rv_location(ret_type)

return value in a2

gen_call(frame, label, args, rv)

Generate instructions for a function call.

gen_epilogue(frame)

Return epilogue sequence

gen_function_enter(args)

Generate code to extract arguments from the proper locations

The default implementation tries to use registers and move instructions.

Parameters:args – an iterable of virtual registers in which the arguments must be placed.
gen_prologue(frame)

Returns prologue instruction sequence

get_runtime()

Retrieve the runtime for this target

move(dst, src)

Generate a move from src to dst

Testing

The xtensa backend

You can run xtensa with qemu:

$ qemu-system-xtensa -M lx60 -m 96M -pflash lx60.flash -serial stdio

This will run the lx60 emulated board. This is an Avnet board with an fpga and an emulated xtensa core on it. This board can boot from parallel flash (pflash).

The memory is mapped as follows, you can see it in the qemu monitor with the ‘info mtree’ command:

(qemu) info mtree
address-space: memory
  0000000000000000-ffffffffffffffff (prio 0, RW): system
    0000000000000000-0000000005ffffff (prio 0, RW): lx60.dram
    00000000f0000000-00000000fdffffff (prio 0, RW): lx60.io
      00000000f8000000-00000000f83fffff (prio 0, R-): lx60.io.flash
      00000000fd020000-00000000fd02ffff (prio 0, RW): lx60.fpga
      00000000fd030000-00000000fd030053 (prio 0, RW): open_eth.regs
      00000000fd030400-00000000fd0307ff (prio 0, RW): open_eth.desc
      00000000fd050020-00000000fd05003f (prio 0, RW): serial
      00000000fd800000-00000000fd803fff (prio 0, RW): open_eth.ram
    00000000fe000000-00000000fe3fffff (prio 0, RW): alias lx60.flash @lx60.io.flash 0000000000000000-00000000003fffff

address-space: I/O
  0000000000000000-000000000000ffff (prio 0, RW): io

address-space: cpu-memory
  0000000000000000-ffffffffffffffff (prio 0, RW): system
    0000000000000000-0000000005ffffff (prio 0, RW): lx60.dram
    00000000f0000000-00000000fdffffff (prio 0, RW): lx60.io
      00000000f8000000-00000000f83fffff (prio 0, R-): lx60.io.flash
      00000000fd020000-00000000fd02ffff (prio 0, RW): lx60.fpga
      00000000fd030000-00000000fd030053 (prio 0, RW): open_eth.regs
      00000000fd030400-00000000fd0307ff (prio 0, RW): open_eth.desc
      00000000fd050020-00000000fd05003f (prio 0, RW): serial
      00000000fd800000-00000000fd803fff (prio 0, RW): open_eth.ram
    00000000fe000000-00000000fe3fffff (prio 0, RW): alias lx60.flash @lx60.io.flash 0000000000000000-00000000003fffff

memory-region: lx60.io.flash
  0000000008000000-00000000083fffff (prio 0, R-): lx60.io.flash

The lx60 emulation has also an mmu, which means it uses a memory translation unit. Therefore, the RAM is mapped from 0xd8000000 to 0x00000000.

A working memory map for this target is:

MEMORY flash LOCATION=0xfe000000 SIZE=0x10000 {
    SECTION(reset)
    ALIGN(4)
    SECTION(code)
}

MEMORY ram LOCATION=0xd8000000 SIZE=0x10000 {
    SECTION(data)
}

Code starts to run from the first byte of the flash image, and is mapped at 0xfe000000.