#include "nemu.h"
#include "device/mmio.h"

#define PMEM_SIZE (128 * 1024 * 1024)

#define pmem_rw(addr, type) *(type *)({\
    Assert(addr < PMEM_SIZE, "physical address(0x%08x) is out of bound", addr); \
    guest_to_host(addr); \
    })

uint8_t pmem[PMEM_SIZE];

/* Memory accessing interfaces */

__attribute__((hot)) uint32_t paddr_read(paddr_t addr, int len) {
    static const uint32_t niddle[] = {0, 0xff, 0xffff, 0xffffff, 0xffffffff};

#ifndef DISABLE_MMIO
    if(const auto mmio_id = is_mmio(addr); RLIB_MACRO_LIKELY(-1 == mmio_id)) {
#endif
      return pmem_rw(addr, uint32_t) & niddle[len];
#ifndef DISABLE_MMIO
    }
    else {
      return mmio_read(addr, len, mmio_id);
    }
#endif
}

void paddr_write(paddr_t addr, uint32_t data, int len) {
#ifndef DISABLE_MMIO
  if(const auto mmio_id = is_mmio(addr); RLIB_MACRO_LIKELY(-1 == mmio_id)) {
#endif
    memcpy(guest_to_host(addr), &data, len);
#ifndef DISABLE_MMIO
  }
  else {
    mmio_write(addr, len, data, mmio_id);
  }
#endif
}


// len is Bytes.
uint32_t vaddr_read(vaddr_t addr, int len) {
  return paddr_read(addr, len);
}

// len is Bytes.
void vaddr_write(vaddr_t addr, uint32_t data, int len) {
  paddr_write(addr, data, len);
}
