<commit_before>//
// vr4300/cp0.c: VR4300 system control coprocessor.
//
// CEN64: Cycle-Accurate Nintendo 64 Simulator.
// Copyright (C) 2014, <NAME>.
//
// This file is subject to the terms and conditions defined in
// 'LICENSE', which is part of this source code package.
//

#include "common.h"
#include "tlb/tlb.h"
#include "vr4300/cp0.h"
#include "vr4300/cpu.h"

static const uint64_t vr4300_cp0_reg_masks[32] = {
  0x000000008000003FULL, //  0: VR4300_CP0_REGISTER_INDEX
  0x000000000000003FULL, //  1: VR4300_CP0_REGISTER_RANDOM
  0x000000007FFFFFFFULL, //  2: VR4300_CP0_REGISTER_ENTRYLO0
  0x000000007FFFFFFFULL, //  3: VR4300_CP0_REGISTER_ENTRYLO1
  0xFFFFFFFFFFFFFFF0ULL, //  4: VR4300_CP0_REGISTER_CONTEXT
  0x0000000001FFE000ULL, //  5: VR4300_CP0_REGISTER_PAGEMASK
  0xFFFFFFFFFFFFFFFFULL, //  6: VR4300_CP0_REGISTER_WIRED
  0x000000000000003FULL, //  7:
  0xFFFFFFFFFFFFFFFFULL, //  8: VR4300_CP0_REGISTER_BADVADDR
  0x00000000FFFFFFFFULL, //  9: VR4300_CP0_REGISTER_COUNT
  0xC00000FFFFFFE0FFULL, // 10: VR4300_CP0_REGISTER_ENTRYHI
  0x00000000FFFFFFFFULL, // 11: VR4300_CP0_REGISTER_COMPARE
  0x00000000FFFFFFFFULL, // 12: VR4300_CP0_REGISTER_STATUS
  0x00000000B000FFFFULL, // 13: VR4300_CP0_REGISTER_CAUSE
  0xFFFFFFFFFFFFFFFFULL, // 14: VR4300_CP0_REGISTER_EPC
  0x000000000000FFFFULL, // 15; VR4300_CP0_REGISTER_PRID
  0x000000007FFFFFFFULL, // 16: VR4300_CP0_REGISTER_CONFIG
  0x00000000FFFFFFFFULL, // 17: VR4300_CP0_REGISTER_LLADDR
  0x00000000FFFFFFFBULL, // 18: VR4300_CP0_REGISTER_WATCHLO
  0x000000000000000FULL, // 19: VR4300_CP0_REGISTER_WATCHHI
  0xFFFFFFFFFFFFFFFFULL, // 20: VR4300_CP0_REGISTER_XCONTEXT
  0xFFFFFFFFFFFFFFFFULL, // 21:
  0xFFFFFFFFFFFFFFFFULL, // 22:
  0xFFFFFFFFFFFFFFFFULL, // 23:
  0xFFFFFFFFFFFFFFFFULL, // 24:
  0xFFFFFFFFFFFFFFFFULL, // 25:
  0x0000000000000000ULL, // 26: VR4300_CP0_REGISTER_PARITYERROR
  0x0000000000000000ULL, // 27: VR4300_CP0_REGISTER_CACHEERR
  0x000000000FFFFFC0ULL, // 28: VR4300_CP0_REGISTER_TAGLO
  0x0000000000000000ULL, // 29: VR4300_CP0_REGISTER_TAGHI
  0xFFFFFFFFFFFFFFFFULL, // 30: VR4300_CP0_REGISTER_ERROREPC
  0xFFFFFFFFFFFFFFFFULL, // 31
};

static inline uint64_t mask_reg(unsigned reg, uint64_t data) {
  return vr4300_cp0_reg_masks[reg] & data;
};

//
// DMFC0
//
int VR4300_DMFC0(struct vr4300 *vr4300,
  uint32_t iw, uint64_t rs, uint64_t rt) {
  struct vr4300_exdc_latch *exdc_latch = &vr4300->pipeline.exdc_latch;
  unsigned dest = GET_RT(iw);
  unsigned src = GET_RD(iw);

  exdc_latch->result = mask_reg(src, vr4300->regs[32 + src]);
  exdc_latch->dest = dest;
  return 0;
}

//
// DMTC0
//
int VR4300_DMTC0(struct vr4300 *vr4300,
  uint32_t iw, uint64_t rs, uint64_t rt) {
  unsigned dest = 32 + GET_RD(iw);

  if (dest == VR4300_CP0_REGISTER_COMPARE)
    vr4300->regs[VR4300_CP0_REGISTER_CAUSE] &= ~0x8000;

  vr4300->regs[dest] = rt;
  return 0;
}

//
// ERET
//
int VR4300_ERET(struct vr4300 *vr4300,
  uint32_t iw, uint64_t rs, uint64_t rt) {
  struct vr4300_icrf_latch *icrf_latch = &vr4300->pipeline.icrf_latch;
  struct vr4300_exdc_latch *exdc_latch = &vr4300->pipeline.exdc_latch;
  struct vr4300_pipeline *pipeline = &vr4300->pipeline;

  int32_t status = vr4300->regs[VR4300_CP0_REGISTER_STATUS];

  if (status & 0x4) {
    icrf_latch->pc = vr4300->regs[VR4300_CP0_REGISTER_ERROREPC];
    status &= ~0x4;
  }

  else {
    icrf_latch->pc = vr4300->regs[VR4300_CP0_REGISTER_EPC];
    status &= ~0x2;
  }

  // Until we delay CP0 writes, we have to kill ourselves
  // to prevent squashing this instruction the next cycle.
  exdc_latch->common.fault = ~0;
  icrf_latch->common.fault = ~0;

  vr4300->regs[PIPELINE_CYCLE_TYPE] = 0;
  pipeline->exception_history = 0;
  pipeline->fault_present = true;

  vr4300->regs[VR4300_CP0_REGISTER_STATUS] = status;
  pipeline->icrf_latch.segment = get_default_segment();
  pipeline->exdc_latch.segment = get_default_segment();
  // vr4300->llbit = 0;
  return 0;
}

//
// MFC0
//
int VR4300_MFC0(struct vr4300 *vr4300, 
  uint32_t iw, uint64_t rs, uint64_t rt) {
  struct vr4300_exdc_latch *exdc_latch = &vr4300->pipeline.exdc_latch;
  unsigned dest = GET_RT(iw);
  unsigned src = GET_RD(iw);

  exdc_latch->result = mask_reg(src, vr4300->regs[32 + src]);
  exdc_latch->dest = (int32_t) dest;
  return 0;
}

//
// MTC0
//
int VR4300_MTC0(struct vr4300 *vr4300,
  uint32_t iw, uint64_t rs, uint64_t rt) {
  unsigned dest = 32 + GET_RD(iw);

  if (dest == VR4300_CP0_REGISTER_COMPARE)<commit_msg>Fix a careless mistake in the last commit.<commit_after>//
// vr4300/cp0.c: VR4300 system control coprocessor.
//
// CEN64: Cycle-Accurate Nintendo 64 Simulator.
// Copyright (C) 2014, <NAME>.
//
// This file is subject to the terms and conditions defined in
// 'LICENSE', which is part of this source code package.
//

#include "common.h"
#include "tlb/tlb.h"
#include "vr4300/cp0.h"
#include "vr4300/cpu.h"

static const uint64_t vr4300_cp0_reg_masks[32] = {
  0x000000008000003FULL, //  0: VR4300_CP0_REGISTER_INDEX
  0x000000000000003FULL, //  1: VR4300_CP0_REGISTER_RANDOM
  0x000000007FFFFFFFULL, //  2: VR4300_CP0_REGISTER_ENTRYLO0
  0x000000007FFFFFFFULL, //  3: VR4300_CP0_REGISTER_ENTRYLO1
  0xFFFFFFFFFFFFFFF0ULL, //  4: VR4300_CP0_REGISTER_CONTEXT
  0x0000000001FFE000ULL, //  5: VR4300_CP0_REGISTER_PAGEMASK
  0xFFFFFFFFFFFFFFFFULL, //  6: VR4300_CP0_REGISTER_WIRED
  0x000000000000003FULL, //  7:
  0xFFFFFFFFFFFFFFFFULL, //  8: VR4300_CP0_REGISTER_BADVADDR
  0x00000000FFFFFFFFULL, //  9: VR4300_CP0_REGISTER_COUNT
  0xC00000FFFFFFE0FFULL, // 10: VR4300_CP0_REGISTER_ENTRYHI
  0x00000000FFFFFFFFULL, // 11: VR4300_CP0_REGISTER_COMPARE
  0x00000000FFFFFFFFULL, // 12: VR4300_CP0_REGISTER_STATUS
  0x00000000B000FFFFULL, // 13: VR4300_CP0_REGISTER_CAUSE
  0xFFFFFFFFFFFFFFFFULL, // 14: VR4300_CP0_REGISTER_EPC
  0x000000000000FFFFULL, // 15; VR4300_CP0_REGISTER_PRID
  0x000000007FFFFFFFULL, // 16: VR4300_CP0_REGISTER_CONFIG
  0x00000000FFFFFFFFULL, // 17: VR4300_CP0_REGISTER_LLADDR
  0x00000000FFFFFFFBULL, // 18: VR4300_CP0_REGISTER_WATCHLO
  0x000000000000000FULL, // 19: VR4300_CP0_REGISTER_WATCHHI
  0xFFFFFFFFFFFFFFFFULL, // 20: VR4300_CP0_REGISTER_XCONTEXT
  0xFFFFFFFFFFFFFFFFULL, // 21:
  0xFFFFFFFFFFFFFFFFULL, // 22:
  0xFFFFFFFFFFFFFFFFULL, // 23:
  0xFFFFFFFFFFFFFFFFULL, // 24:
  0xFFFFFFFFFFFFFFFFULL, // 25:
  0x0000000000000000ULL, // 26: VR4300_CP0_REGISTER_PARITYERROR
  0x0000000000000000ULL, // 27: VR4300_CP0_REGISTER_CACHEERR
  0x000000000FFFFFC0ULL, // 28: VR4300_CP0_REGISTER_TAGLO
  0x0000000000000000ULL, // 29: VR4300_CP0_REGISTER_TAGHI
  0xFFFFFFFFFFFFFFFFULL, // 30: VR4300_CP0_REGISTER_ERROREPC
  0xFFFFFFFFFFFFFFFFULL, // 31
};

static inline uint64_t mask_reg(unsigned reg, uint64_t data) {
  return vr4300_cp0_reg_masks[reg] & data;
};

//
// DMFC0
//
int VR4300_DMFC0(struct vr4300 *vr4300,
  uint32_t iw, uint64_t rs, uint64_t rt) {
  struct vr4300_exdc_latch *exdc_latch = &vr4300->pipeline.exdc_latch;
  unsigned dest = GET_RT(iw);
  unsigned src = GET_RD(iw);

  exdc_latch->result = mask_reg(src, vr4300->regs[32 + src]);
  exdc_latch->dest = dest;
  return 0;
}

//
// DMTC0
//
int VR4300_DMTC0(struct vr4300 *vr4300,
  uint32_t iw, uint64_t rs, uint64_t rt) {
  unsigned dest = 32 + GET_RD(iw);

  if (dest == VR4300_CP0_REGISTER_COMPARE)
    vr4300->regs[VR4300_CP0_REGISTER_CAUSE] &= ~0x8000;

  vr4300->regs[dest] = rt;
  return 0;
}

//
// ERET
//
int VR4300_ERET(struct vr4300 *vr4300,
  uint32_t iw, uint64_t rs, uint64_t rt) {
  struct vr4300_icrf_latch *icrf_latch = &vr4300->pipeline.icrf_latch;
  struct vr4300_rfex_latch *rfex_latch = &vr4300->pipeline.rfex_latch;
  struct vr4300_exdc_latch *exdc_latch = &vr4300->pipeline.exdc_latch;
  struct vr4300_pipeline *pipeline = &vr4300->pipeline;

  int32_t status = vr4300->regs[VR4300_CP0_REGISTER_STATUS];

  if (status & 0x4) {
    icrf_latch->pc = vr4300->regs[VR4300_CP0_REGISTER_ERROREPC];
    status &= ~0x4;
  }

  else {
    icrf_latch->pc = vr4300->regs[VR4300_CP0_REGISTER_EPC];
    status &= ~0x2;
  }

  // Until we delay CP0 writes, we have to kill ourselves
  // to prevent squashing this instruction the next cycle.
  exdc_latch->common.fault = ~0;
  rfex_latch->common.fault = ~0;

  vr4300->regs[PIPELINE_CYCLE_TYPE] = 4;
  pipeline->exception_history = 0;
  pipeline->fault_present = true;

  vr4300->regs[VR4300_CP0_REGISTER_STATUS] = status;

  pipeline->icrf_latch.segment = get_default_segment(); //get_segment(icrf_latch->pc, status);
  pipeline->exdc_latch.segment = get_default_segment();
  // vr4300->llbit = 0;
  return 1;
}

//
// MFC0
//
int VR4300_MFC0(struct vr4300 *vr4300, 
  uint32_t iw, uint64_t rs, uint64_t rt) {
  struct vr4300_exdc_latch *exdc_latch = &vr4300->pipeline.exdc_latch;
  unsigned dest = GET_RT(iw);
  unsigned src = GET_RD(iw);

  exdc_latch->result = mask_reg(src, vr4300->regs[32 + src]);
  exdc_latch->dest = (int32_t) dest;
  return 0;
}

//
// MTC0
//
int VR4300_MTC0(struct vr4300 *vr4300,
  uint32_t iw, uint64_t rs, uint64_t rt) {
  unsigned dest = 32 + GET_RD(iw);

  if (dest == VR4300_CP0_REGISTER_COMPARE)
{'fraction_non_alphanumeric': 0.10899424014178112, 'fraction_numerical': 0.16282676118741693, 'mean_word_length': 4.512210012210012, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 78, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6559169', 'n_tokens_mistral': 4756, 'n_tokens_neox': 3819, 'n_words': 658}