Exemplo n.º 1
0
// Data cache fetch stage.
cen64_flatten static inline void rsp_df_stage(struct rsp *rsp) {
  struct rsp_dfwb_latch *dfwb_latch = &rsp->pipeline.dfwb_latch;
  struct rsp_exdf_latch *exdf_latch = &rsp->pipeline.exdf_latch;
  const struct rsp_mem_request *request = &exdf_latch->request;
  uint32_t addr;

  dfwb_latch->common = exdf_latch->common;
  dfwb_latch->result = exdf_latch->result;

  if (request->type == RSP_MEM_REQUEST_NONE)
    return;

  addr = request->addr & 0xFFF;

  // Vector unit DMEM access.
  if (request->type != RSP_MEM_REQUEST_INT_MEM) {
    uint16_t *regp = rsp->cp2.regs[request->packet.p_vect.dest].e;
    unsigned element = request->packet.p_vect.element;
    rsp_vect_t reg, dqm;

    reg = rsp_vect_load_unshuffled_operand(regp);
    dqm = rsp_vect_load_unshuffled_operand(exdf_latch->
      request.packet.p_vect.vdqm.e);

    // Make sure the vector data doesn't get
    // written into the scalar part of the RF.
    dfwb_latch->result.dest = 0;

    exdf_latch->request.packet.p_vect.vldst_func(
      rsp, addr, element, regp, reg, dqm);
  }

  // Scalar unit DMEM access.
  else {
    uint32_t rdqm = request->packet.p_int.rdqm;
    uint32_t wdqm = request->packet.p_int.wdqm;
    uint32_t data = request->packet.p_int.data;
    unsigned rshift = request->packet.p_int.rshift;
    uint32_t word;

    memcpy(&word, rsp->mem + addr, sizeof(word));

    word = byteswap_32(word);
    dfwb_latch->result.result = rdqm & (((int32_t) word) >> rshift);
    word = byteswap_32((word & ~wdqm) | (data & wdqm));

    memcpy(rsp->mem + addr, &word, sizeof(word));
  }
}
Exemplo n.º 2
0
// Reads a word from cartridge ROM.
int read_cart_rom(void *opaque, uint32_t address, uint32_t *word) {
  struct pi_controller *pi = (struct pi_controller *) opaque;
  unsigned offset = (address - ROM_CART_BASE_ADDRESS) & ~0x3;

  // TODO: Need to figure out correct behaviour.
  // Should this even happen to begin with?
  if (pi->rom == NULL || offset > pi->rom_size - sizeof(*word)) {
    *word = 0;
    return 0;
  }

  memcpy(word, pi->rom + offset, sizeof(*word));
  *word = byteswap_32(*word);
  return 0;
}
Exemplo n.º 3
0
// DMA into the RSP's memory space.
void rsp_dma_read(struct rsp *rsp) {
  uint32_t length = (rsp->regs[RSP_CP0_REGISTER_DMA_READ_LENGTH] & 0xFFF) + 1;
  uint32_t skip = rsp->regs[RSP_CP0_REGISTER_DMA_READ_LENGTH] >> 20 & 0xFFF;
  unsigned count = rsp->regs[RSP_CP0_REGISTER_DMA_READ_LENGTH] >> 12 & 0xFF;
  unsigned j, i = 0;

  // Force alignment.
  length = (length + 0x7) & ~0x7;
  rsp->regs[RSP_CP0_REGISTER_DMA_CACHE] &= ~0x3;
  rsp->regs[RSP_CP0_REGISTER_DMA_DRAM] &= ~0x7;

  // Check length.
  if (((rsp->regs[RSP_CP0_REGISTER_DMA_CACHE] & 0xFFF) + length) > 0x1000)
    length = 0x1000 - (rsp->regs[RSP_CP0_REGISTER_DMA_CACHE] & 0xFFF);

  do {
    uint32_t source = rsp->regs[RSP_CP0_REGISTER_DMA_DRAM] & 0x7FFFFC;
    uint32_t dest = rsp->regs[RSP_CP0_REGISTER_DMA_CACHE] & 0x1FFC;
    j = 0;

    do {
      uint32_t source_addr = (source + j) & 0x7FFFFC;
      uint32_t dest_addr = (dest + j) & 0x1FFC;
      uint32_t word;

      bus_read_word(rsp, source_addr, &word);

      // Update opcode cache.
      if (dest_addr & 0x1000) {
        rsp->opcode_cache[(dest_addr - 0x1000) >> 2] =
          *rsp_decode_instruction(word);
      } else {
        word = byteswap_32(word);
      }

      memcpy(rsp->mem + dest_addr, &word, sizeof(word));
      j += 4;
    } while (j < length);

    rsp->regs[RSP_CP0_REGISTER_DMA_DRAM] += length + skip;
    rsp->regs[RSP_CP0_REGISTER_DMA_CACHE] += length;
  } while(++i <= count);
Exemplo n.º 4
0
// Performs an (instantaneous) DMA.
void ai_dma(struct ai_controller *ai) {
  struct bus_controller *bus;

  // Shove things into the audio context, slide the window.
  memcpy(&bus, ai, sizeof(bus));

  // Need to raise an interrupt when the DMA engine
  // is doing the last 8-byte data bus transfer...
  if (likely(ai->fifo[ai->fifo_ri].length > 0)) {
    unsigned freq = (double) NTSC_DAC_FREQ / (ai->regs[AI_DACRATE_REG] + 1);
    unsigned samples = ai->fifo[ai->fifo_ri].length / 4;// - 1;

    // Shovel things into the audio context.
    uint8_t buf[0x40000];
    unsigned i;

    ALuint buffer;
    ALint val;

    alGetSourcei(ai->ctx.source, AL_BUFFERS_PROCESSED, &val);

    if (val) {
      for (i = 0; i < ai->fifo[ai->fifo_ri].length / 4; i++) {
        uint32_t word;

        // Byteswap audio buffer to native format.
        // TODO: Can we specify endian-ness somehow?
        memcpy(&word, bus->ri->ram + (ai->fifo[
          ai->fifo_ri].address + sizeof(word) * i), sizeof(word));
        word = byteswap_32(word);
        memcpy(buf + sizeof(word) * i, &word, sizeof(word));
      }

      alSourceUnqueueBuffers(ai->ctx.source, 1, &buffer);
      alBufferData(buffer, AL_FORMAT_STEREO16, buf,
        ai->fifo[ai->fifo_ri].length, 44100 /* ai->ctx.frequency */);
      alSourceQueueBuffers(ai->ctx.source, 1, &buffer);

      alGetSourcei(ai->ctx.source, AL_SOURCE_STATE, &val);

      if(val != AL_PLAYING)
        alSourcePlay(ai->ctx.source);

      if (alGetError() != AL_NO_ERROR) {
        fprintf(stderr, "OpenAL is angry!\n");
        exit(255);
      }
    }

    ai->counter = (62500000.0 / freq) * samples;
    //printf("Wait %lu cycles to raise interrupt.\n", ai->counter);
  }

  // If the length was zero, just interrupt now?
  else {
    signal_rcp_interrupt(bus->vr4300, MI_INTR_AI);

    ai->fifo_ri = (ai->fifo_ri == 1) ? 0 : 1;
    ai->regs[AI_STATUS_REG] &= ~0x80000001;
    ai->counter = 0xFFFFFFFFU;
    ai->fifo_count--;
  }

  if (ai->fifo_count > 0)
    ai->regs[AI_STATUS_REG] |= 0x40000000;
}