<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "mmu.h"
#include "mfp.h"

#define MFPSIZE 48
#define MFPBASE 0xfffa00

#define GPIP   0
#define AER    1
#define DDR    2
#define IERA   3
#define IERB   4
#define IPRA   5
#define IPRB   6
#define ISRA   7
#define ISRB   8
#define IMRA   9
#define IMRB  10
#define VR    11
#define TACR  12
#define TBCR  13
#define TCDCR 14
#define TADR  15
#define TBDR  16
#define TCDR  17
#define TDDR  18
#define SCR   19
#define UCR   20
#define RSR   21
#define TSR   22
#define UDR   23

#define INT_TIMERA 13
#define INT_TIMERB  8
#define INT_TIMERC  5
#define INT_TIMERD  4

#define IER ((mfpreg[IERA]<<8)|mfpreg[IERB])
#define IPR ((mfpreg[IPRA]<<8)|mfpreg[IPRB])
#define ISR ((mfpreg[ISRA]<<8)|mfpreg[ISRB])
#define IMR ((mfpreg[IMRA]<<8)|mfpreg[IMRB])

#define MFPBASEFREQ 2457600
#define MFPFREQ (MFPBASEFREQ*313)

static long lastcpucnt;
static long precnt[4];
static int intnum[4] = { INT_TIMERA, INT_TIMERB, INT_TIMERC, INT_TIMERD };
static long divider[8] = { 0, 4, 10, 16, 50, 64, 100, 200 };
static BYTE mfpreg[24];
static BYTE timercnt[4];

static BYTE mfp_read_byte(LONG addr)
{
  int r;

  if(!(addr&1)) return 0;
  addr -= MFPBASE;
  r = (addr>>1)%24;

  switch(r) {
  case GPIP:
    return mfpreg[GPIP]|0x80;
  case TADR:
  case TBDR:
  case TCDR:
  case TDDR:
    return timercnt[r-TADR];
  default:
    return mfpreg[r];
  }
}

static WORD mfp_read_word(LONG addr)
{
  return (mfp_read_byte(addr)<<8)|mfp_read_byte(addr+1);
}

static LONG mfp_read_long(LONG addr)
{
  return ((mfp_read_byte(addr)<<24)|
       (mfp_read_byte(addr+1)<<16)|
       (mfp_read_byte(addr+2)<<8)|
       (mfp_read_byte(addr+3)));
}

static void mfp_write_byte(LONG addr, BYTE data)
{
  int r;
  
  if(!(addr&1)) return;

  addr -= MFPBASE;
  r = (addr>>1)%24;

  switch(r) {
  case TACR:
    if(!(mfpreg[TACR]&0xf) && data&0x7) {
      if(data > 7) printf("DEBUG: MFP not fully implemented.\n");
      precnt[0] = divider[data&0x7]*313;
      //      precnt[0] = MFPFREQ/divider[data&0x7];
    }
    break;
  case TBCR:
    if(!(mfpreg[TBCR]&0xf) && data&0x7) {
      if(data > 7) printf("DEBUG: MFP not fully implemented.\n");
      precnt[1] = divider[data&0x7]*313;
      //      precnt[1] = MFPFREQ/divider[data&0x7];
    }
    break;
  case TCDCR:
    if(!(mfpreg[TCDCR]&0x7) && data&0x70) {
      precnt[2] = MFPFREQ/divider[(data&0x70)>>4]*313;
      //      precnt[2] = MFPFREQ/divider[(data&0x70)>>4];
    }
    if(!(mfpreg[TCDCR]&0x7) && data&0x7) {
      precnt[3] = MFPFREQ/divider[data&0x7]*313;
      //      precnt[3] = MFPFREQ/divider[data&0x7];
    }
    break;
  case TADR:
    if(!(mfpreg[TACR]&0xf)) timercnt[0] = data;
    break;
  case TBDR:
    if(!(mfpreg[TBCR]&0xf)) timercnt[1] = data;
    break;
  case TCDR:
    if(!(mfpreg[TCDCR]&0x70)) timercnt[2] = data;
    break;
  case TDDR:
    if(!(mfpreg[TCDCR]&0x7)) timercnt[3] = data;
    break;
  }
  
  mfpreg[r] = data;
}

static void mfp_write_word(LONG addr, WORD data)
{
  mfp_write_byte(addr, (data&0xff00)>>8);
  mfp_write_byte(addr+1, (data&0xff));
}

static void mfp_write_long(LONG addr, LONG data)
{
  mfp_write_byte(addr, (data&0xff000000)>>24);
  mfp_write_byte(addr+1, (data&0xff0000)>>16);
  mfp_write_byte(addr+2, (data&0xff00)>>8);
  mfp_write_byte(addr+3, (data&0xff));
}

void mfp_init()
{
  struct mmu *mfp;

  mfp = (struct mmu *)malloc(sizeof(struct mmu));
  if(!mfp) {
    return;
  }
  mfp->start = MFPBASE;
  mfp->size = MFPSIZE;
  mfp->name = strdup("MFP");
  mfp->read_byte = mfp_read_byte;
  mfp->read_word = mfp_read_word;
  mfp->read_long = mfp_read_long;
  mfp->write_byte = mfp_write_byte;
  mfp->write_word = mfp_write_word;
  mfp->write_long = mfp_write_long;

  mmu_register(mfp);
}

void mfp_print_status()
{
  int i;
  printf("MFP: ");
  for(i=0;i<24;i++)
    printf("%02x ",mfpreg[i]);
  printf("\n");
  for(i=0;i<4;i++)
    printf(" Prediv %c: %ld %d\n", i+'A', precnt[i], timercnt[i]);
  printf("\n");
}

static void update_timer(int tnum, long cycles)
{
  int d;
  int iermask;
  int ierreg;

  d = 0;

  switch(tnum) {
  case 0:
    if(!(mfpreg[TACR]&0xf)) return;
    if((mfpreg[TACR]&0xf) == 8) return;
    d = divider[(mfpreg[TACR]&0x7)];
    ierreg = 0;
    iermask = 0x20;
    break;
  case 1:
    if(!(mfpreg[TBCR]&0xf)) return;
    if((mfpreg[TBCR]&0xf) == 8) return;
    d = divider[(mfpreg[TBCR]&0x7)];
    ierreg = 0;
    iermask = 0x1;
    break;
  case 2:
    if(!(mfpreg[TCDCR]&0x70)) return;
    d = divider[(mfpreg[TCDCR]&0x70)>>4];
    ierreg = 1;
    iermask = 0x20;
    break;
  case 3:
    if(!(mfpreg[TCDCR]&0x7)) return;
    d = divider[(mfpreg[TCDCR]&0x7)];
    ierreg = 1;
    iermask = 0x10;
    break;
  }

  if(!d) return;

  //  printf("DEBUG: Calling update_timer(%d, %ld)\n", tnum, cycles);

  precnt[tnum] -= cycles;
  if(precnt[tnum] < 0) {
    precnt[tnum] += d*313;
    //    precnt[tnum] += MFPFREQ/d;<commit_msg>Fixed some timer initialisation bugs<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "mmu.h"
#include "mfp.h"

#define MFPSIZE 48
#define MFPBASE 0xfffa00

#define GPIP   0
#define AER    1
#define DDR    2
#define IERA   3
#define IERB   4
#define IPRA   5
#define IPRB   6
#define ISRA   7
#define ISRB   8
#define IMRA   9
#define IMRB  10
#define VR    11
#define TACR  12
#define TBCR  13
#define TCDCR 14
#define TADR  15
#define TBDR  16
#define TCDR  17
#define TDDR  18
#define SCR   19
#define UCR   20
#define RSR   21
#define TSR   22
#define UDR   23

#define INT_TIMERA 13
#define INT_TIMERB  8
#define INT_TIMERC  5
#define INT_TIMERD  4

#define IER ((mfpreg[IERA]<<8)|mfpreg[IERB])
#define IPR ((mfpreg[IPRA]<<8)|mfpreg[IPRB])
#define ISR ((mfpreg[ISRA]<<8)|mfpreg[ISRB])
#define IMR ((mfpreg[IMRA]<<8)|mfpreg[IMRB])

#define MFPBASEFREQ 2457600
#define MFPFREQ (MFPBASEFREQ*313)

static long lastcpucnt;
static long precnt[4];
static int intnum[4] = { INT_TIMERA, INT_TIMERB, INT_TIMERC, INT_TIMERD };
static long divider[8] = { 0, 4, 10, 16, 50, 64, 100, 200 };
static BYTE mfpreg[24];
static BYTE timercnt[4];

static BYTE mfp_read_byte(LONG addr)
{
  int r;

  if(!(addr&1)) return 0;
  addr -= MFPBASE;
  r = (addr>>1)%24;

  switch(r) {
  case GPIP:
    return mfpreg[GPIP]|0x80;
  case TADR:
  case TBDR:
  case TCDR:
  case TDDR:
    return timercnt[r-TADR];
  default:
    return mfpreg[r];
  }
}

static WORD mfp_read_word(LONG addr)
{
  return (mfp_read_byte(addr)<<8)|mfp_read_byte(addr+1);
}

static LONG mfp_read_long(LONG addr)
{
  return ((mfp_read_byte(addr)<<24)|
       (mfp_read_byte(addr+1)<<16)|
       (mfp_read_byte(addr+2)<<8)|
       (mfp_read_byte(addr+3)));
}

static void mfp_write_byte(LONG addr, BYTE data)
{
  int r;
  
  if(!(addr&1)) return;

  addr -= MFPBASE;
  r = (addr>>1)%24;

  switch(r) {
  case TACR:
    if(!(mfpreg[TACR]&0xf) && data&0x7) {
      if(data > 7) printf("DEBUG: MFP not fully implemented.\n");
      precnt[0] = 313*divider[data&0x7];
    }
    break;
  case TBCR:
    if(!(mfpreg[TBCR]&0xf) && data&0x7) {
      if(data > 7) printf("DEBUG: MFP not fully implemented.\n");
      precnt[1] = 313*divider[data&0x7];
    }
    break;
  case TCDCR:
    if(!(mfpreg[TCDCR]&0x70) && data&0x70) {
      precnt[2] = 313*divider[(data&0x70)>>4];
    }
    if(!(mfpreg[TCDCR]&0x7) && data&0x7) {
      precnt[3] = 313*divider[data&0x7];
    }
    break;
  case TADR:
    if(!(mfpreg[TACR]&0xf)) timercnt[0] = data;
    break;
  case TBDR:
    if(!(mfpreg[TBCR]&0xf)) timercnt[1] = data;
    break;
  case TCDR:
    if(!(mfpreg[TCDCR]&0x70)) timercnt[2] = data;
    break;
  case TDDR:
    if(!(mfpreg[TCDCR]&0x7)) timercnt[3] = data;
    break;
  }
  
  mfpreg[r] = data;
}

static void mfp_write_word(LONG addr, WORD data)
{
  mfp_write_byte(addr, (data&0xff00)>>8);
  mfp_write_byte(addr+1, (data&0xff));
}

static void mfp_write_long(LONG addr, LONG data)
{
  mfp_write_byte(addr, (data&0xff000000)>>24);
  mfp_write_byte(addr+1, (data&0xff0000)>>16);
  mfp_write_byte(addr+2, (data&0xff00)>>8);
  mfp_write_byte(addr+3, (data&0xff));
}

void mfp_init()
{
  struct mmu *mfp;

  mfp = (struct mmu *)malloc(sizeof(struct mmu));
  if(!mfp) {
    return;
  }
  mfp->start = MFPBASE;
  mfp->size = MFPSIZE;
  mfp->name = strdup("MFP");
  mfp->read_byte = mfp_read_byte;
  mfp->read_word = mfp_read_word;
  mfp->read_long = mfp_read_long;
  mfp->write_byte = mfp_write_byte;
  mfp->write_word = mfp_write_word;
  mfp->write_long = mfp_write_long;

  mmu_register(mfp);
}

void mfp_print_status()
{
  int i;
  printf("MFP: ");
  for(i=0;i<24;i++)
    printf("%02x ",mfpreg[i]);
  printf("\n");
  for(i=0;i<4;i++)
    printf(" Prediv %c: %ld %d\n", i+'A', precnt[i], timercnt[i]);
  printf("\n");
}

static void update_timer(int tnum, long cycles)
{
  int d;
  int iermask;
  int ierreg;

  d = 0;

  switch(tnum) {
  case 0:
    if(!(mfpreg[TACR]&0xf)) return;
    if((mfpreg[TACR]&0xf) == 8) return;
    d = divider[(mfpreg[TACR]&0x7)];
    ierreg = 0;
    iermask = 0x20;
    break;
  case 1:
    if(!(mfpreg[TBCR]&0xf)) return;
    if((mfpreg[TBCR]&0xf) == 8) return;
    d = divider[(mfpreg[TBCR]&0x7)];
    ierreg = 0;
    iermask = 0x1;
    break;
  case 2:
    if(!(mfpreg[TCDCR]&0x70)) return;
    d = divider[(mfpreg[TCDCR]&0x70)>>4];
    ierreg = 1;
    iermask = 0x20;
    break;
  case 3:
    if(!(mfpreg[TCDCR]&0x7)) return;
    d = divider[(mfpreg[TCDCR]&0x7)];
    ierreg = 1;
    iermask = 0x10;
    break;
  }

  if(!d) return;

  //  printf("DEBUG: Calling update_timer(%d, %ld)\n", tnum, cycles);

  precnt[tnum] -= cycles;
  if(precnt[tnum] < 0) {
    precnt[tnum] += d*313;
{'fraction_non_alphanumeric': 0.17158232432991824, 'fraction_numerical': 0.051640277346579735, 'mean_word_length': 3.5779251539554715, 'pattern_counts': {'":': 0, '<': 47, '<?xml version=': 0, '>': 65, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1925812', 'n_tokens_mistral': 4759, 'n_tokens_neox': 4461, 'n_words': 871}