MAX32660 streaming SPI output
As Chris suggested, the stream can be broken into blocks. With the following buffering code using blocks of 1 to 32 bytes each, the overhead in my case is 30%, which could be acceptable.
#define SPI_BUF_SIZE 8

uint32_t spi_buf[SPI_BUF_SIZE];
uint8_t* spi_ptr = (uint8_t*)spi_buf;
bool     spi_wait = false;

void SPI_Send(char c)
{
  *spi_ptr++ = c;

  if (spi_ptr == (uint8_t*)(spi_buf + SPI_BUF_SIZE))
    {
      spi_ptr = (uint8_t*)spi_buf;
      if (spi_wait)
      while (!(MXC_SPI17Y-&gt;int_fl &amp; MXC_F_SPI17Y_INT_FL_M_DONE));
        spi_wait = true;
      MXC_SPI17Y-&gt;ctrl1  = SPI_BUF_SIZE * 4;           // set tx_num
      MXC_SPI17Y-&gt;int_fl = MXC_F_SPI17Y_INT_FL_M_DONE; // clear master done
      MXC_SPI17Y-&gt;ctrl0 |= MXC_F_SPI17Y_CTRL0_START;   // start transaction
      for (int i=0; i&lt;SPI_BUF_SIZE; i++)
        MXC_SPI17Y-&gt;data32 = spi_buf[i];
    }
}

void SPI_Flush()
{
  int len = spi_ptr - (uint8_t*)spi_buf;
  if (!len)
    return;
  spi_ptr = (uint8_t*)spi_buf;
  
  if (spi_wait)
    while (!(MXC_SPI17Y-&gt;int_fl &amp; MXC_F_SPI17Y_INT_FL_M_DONE));
  spi_wait = true;

  MXC_SPI17Y-&gt;ctrl1  = len;                        // set tx_num
  MXC_SPI17Y-&gt;int_fl = MXC_F_SPI17Y_INT_FL_M_DONE; // clear master done flag
  MXC_SPI17Y-&gt;ctrl0 |= MXC_F_SPI17Y_CTRL0_START;   // start transaction

  uint32_t* p = spi_buf;
  while (len &gt;= 4)
    {
      MXC_SPI17Y-&gt;data32 = *p++;
      len -= 4;
    }
  uint32_t final = *p;
  if (len &gt;= 2)
    {
      *MXC_SPI17Y-&gt;data16 = final;
      final &gt;&gt;= 16;
    }
  if (len &amp; 1)
    *MXC_SPI17Y-&gt;data8 = final;
}

The performance of an application that sends 20 bursts, with a flush after each burst, and total size 355 bytes is as follows:
buf        runtime   thrupt
4  bytes   178 us
8  bytes   161 us
12 bytes   146 us
16 bytes   172 us
20 bytes   132 us
24 bytes   132 us
28 bytes   133 us
32 bytes   133 us    2.7 MB/s
none*      101 us    3.5 MB/s

* setting tx_num to a large value before each burst.
  But this hangs slave_select (and probably other things too).