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
|
// license:BSD-3-Clause
// copyright-holders:David Haywood
#include "emu.h"
#include "arcompact_helper.ipp"
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// IIII I
// LD<zz><.x><.aa><.di> a,[b,s9] 0001 0bbb ssss ssss SBBB DaaZ ZXAA AAAA
// LD<zz><.x><.di> a,[limm] 0001 0110 0000 0000 0111 DRRZ ZXAA AAAA (+ Limm)
// LD<zz><.x><.aa><.di> 0,[b,s9] 0001 0bbb ssss ssss SBBB DaaZ ZX11 1110
// LD<zz><.x><.di> 0,[limm] 0001 0110 0000 0000 0111 DRRZ ZX11 1110 (+ Limm)
//
// PREFETCH<.aa> [b,s9] 0001 0bbb ssss ssss SBBB 0aa0 0011 1110
// PREFETCH [limm] 0001 0110 0000 0000 0111 0RR0 0011 1110 (+ Limm)
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
uint32_t arcompact_device::handleop32_LD_r_o(uint32_t op)
{
uint32_t s = (op & 0x00ff0000) >> 16;
s |= (op & 0x00008000) >> 7;
s = util::sext(s, 9);
uint8_t breg = common32_get_breg(op);
uint8_t areg = common32_get_areg(op);
int X = (op & 0x00000040) >> 6; //op &= ~0x00000040;
int Z = (op & 0x00000180) >> 7; //op &= ~0x00000180;
int a = (op & 0x00000600) >> 9; //op &= ~0x00000600;
// int D = (op & 0x00000800) >> 11;// op &= ~0x00000800; // we don't use the data cache currently
int size = check_limm(breg);
arcompact_handle_ld_helper(op, areg, breg, s, X, Z, a);
return m_pc + size;
}
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// IIII I
// ST<zz><.aa><.di> c,[b,s9] 0001 1bbb ssss ssss SBBB CCCC CCDa aZZR
// ST<zz><.di> c,[limm] 0001 1110 0000 0000 0111 CCCC CCDR RZZR (+ Limm)
// ST<zz><.aa><.di> limm,[b,s9] 0001 1bbb ssss ssss SBBB 1111 10Da aZZR (+ Limm)
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// can be used as a PUSH when breg is stack register (28), s is -4 (0x1fc) Z is 0, D is 0, and a is 1
uint32_t arcompact_device::handleop32_ST_r_o(uint32_t op)
{
uint32_t s = (op & 0x00ff0000) >> 16;
s |= (op & 0x00008000) >> 7;
s = util::sext(s, 9);
uint8_t breg = common32_get_breg(op);
uint8_t creg = common32_get_creg(op);
// int R = (op & 0x00000001) >> 0; // bit 0 is reserved
int Z = (op & 0x00000006) >> 1;
int a = (op & 0x00000018) >> 3;
// int D = (op & 0x00000020) >> 5; // we don't use the data cache currently
int size = check_limm(breg, creg);
// writeback / increment
if (a == 1)
{
if (breg == REG_LIMM)
fatalerror("illegal ST %08x (data size %d mode %d)", op, Z, a); // using the LIMM as the base register and an increment mode is illegal
m_regs[breg] = m_regs[breg] + s;
}
uint32_t address = m_regs[breg];
uint32_t writedata = m_regs[creg];
// are LIMM addresses with 's' offset non-0 ('a' mode 0 / 3) legal?
// not mentioned in docs..
// address manipulation
if (a == 0)
{
address = address + s;
}
else if (a == 3)
{
if (Z == 0)
address = address + (s << 2);
else if (Z == 2)
address = address + (s << 1);
else // Z == 1 and Z == 3 are invalid here
fatalerror("illegal ST %08x (data size %d mode %d)", op, Z, a);
}
// write data
if (Z == 0)
{
WRITE32(address, writedata);
}
else if (Z == 1)
{
WRITE8(address, writedata);
}
else if (Z == 2)
{
WRITE16(address, writedata);
}
else if (Z == 3)
{ // Z == 3 is always illegal
fatalerror("illegal ST %08x (data size %d mode %d)", op, Z, a);
}
// writeback / increment
if (a == 2)
{
if (breg == REG_LIMM)
fatalerror("illegal ST %08x (data size %d mode %d)", op, Z, a); // using the LIMM as the base register and an increment mode is illegal
m_regs[breg] = m_regs[breg] + s;
}
return m_pc + size;
}
|