aboutsummaryrefslogtreecommitdiff
path: root/libpcsxcore/new_dynarec/pcsxmem_inline.c
blob: 90dafa05a51de101caea51141d39160a5dbd36fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
 * (C) Gražvydas "notaz" Ignotas, 2011
 *
 * This work is licensed under the terms of GNU GPL version 2 or later.
 * See the COPYING file in the top-level directory.
 */

static int emit_ldr_type(int type, int offs, int rs, int rt)
{
  switch(type) {
    case LOADB_STUB:
      emit_movsbl_indexed(offs,rs,rt);
      break;
    case LOADBU_STUB:
      emit_movzbl_indexed(offs,rs,rt);
      break;
    case LOADH_STUB:
      emit_movswl_indexed(offs,rs,rt);
      break;
    case LOADHU_STUB:
      emit_movzwl_indexed(offs,rs,rt);
      break;
    case LOADW_STUB:
      emit_readword_indexed(offs,rs,rt);
      break;
    default:
      assert(0);
  }
}

static int emit_str_type(int type, int offs, int rs, int rt)
{
  switch(type) {
    case STOREB_STUB:
      emit_writebyte_indexed(rt,offs,rs);
      break;
    case STOREH_STUB:
      emit_writehword_indexed(rt,offs,rs);
      break;
    case STOREW_STUB:
      emit_writeword_indexed(rt,offs,rs);
      break;
    default:
      assert(0);
  }
}

static void convert_ram_addr(u_int a_rs, u_int a_rt, int rs, int rt)
{
  if(rs<0)
    emit_movimm(a_rt,rt);
  else if((a_rs&~0x60000000)==a_rt)
    emit_andimm(rs,~0x60000000,rt);
  else if((a_rs&~0x00600000)==a_rt)
    emit_andimm(rs,~0x00600000,rt);
  else
    emit_movimm(a_rt,rt);
}

static int pcsx_direct_read(int type, u_int addr, int rs, int rt)
{
  if((addr & 0x1f800000) == 0) {
    assem_debug("pcsx_direct_read %08x ram\n",addr);
    if(rt<0)
      return 1;
    u_int a=(addr&~0x60600000)|0x80000000;
    convert_ram_addr(addr,a,rs,rt);
    emit_ldr_type(type,0,rt,rt);
    return 1;
  }
  if((addr & 0x1ff80000) == 0x1fc00000) {
    assem_debug("pcsx_direct_read %08x bios\n",addr);
    if(rt<0)
      return 1;
    emit_movimm((u_int)&psxR[addr&0x7ffff],rt);
    emit_ldr_type(type,0,rt,rt);
    return 1;
  }
  if((addr & 0xfffff000) == 0x1f800000) {
    assem_debug("pcsx_direct_read %08x scratchpad\n",addr);
    if(rt<0)
      return 1;
    if(type==LOADW_STUB||type==LOADBU_STUB||(addr&0xf00)==0) {
      emit_readword((int)&psxH_ptr,rt);
      emit_ldr_type(type,addr&0xfff,rt,rt);
    } else {
      emit_movimm((u_int)&psxH[addr&0xfff],rt);
      emit_ldr_type(type,0,rt,rt);
    }
    return 1;
  }

  assem_debug("pcsx_direct_read %08x miss\n",addr);
  return 0;
}

static int pcsx_direct_write(int type, u_int addr, int rs, int rt, signed char *regmap)
{
  if((addr & 0x1f800000) == 0) {
    assem_debug("pcsx_direct_write %08x ram\n",addr);
    u_int a=(addr&~0x60600000)|0x80000000;
    convert_ram_addr(addr,a,rs,HOST_TEMPREG);
    emit_str_type(type,0,HOST_TEMPREG,rt);

    int ir=get_reg(regmap,INVCP);
    assert(ir>=0);
    emit_cmpmem_indexedsr12_reg(ir,rs,1);
    emit_callne(invalidate_addr_reg[rs]);
    return 1;
  }
  if((addr & 0xfffff000) == 0x1f800000) {
    assem_debug("pcsx_direct_write %08x scratchpad\n",addr);
    if(type==STOREW_STUB||type==STOREB_STUB||(addr&0xf00)==0) {
      emit_readword((int)&psxH_ptr,HOST_TEMPREG);
      emit_str_type(type,addr&0xfff,HOST_TEMPREG,rt);
    } else {
      emit_movimm((u_int)&psxH[addr&0xfff],HOST_TEMPREG);
      emit_str_type(type,0,HOST_TEMPREG,rt);
    }
    return 1;
  }

  assem_debug("pcsx_direct_write %08x miss\n",addr);
  return 0;
}

// vim:shiftwidth=2:expandtab