cpu_arm_instr_dpi.cc Source File

Back to the index.

cpu_arm_instr_dpi.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2012 Anders Gavare. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * 3. The name of the author may not be used to endorse or promote products
13  * derived from this software without specific prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  *
28  * ARM Data Processing Instructions
29  * --------------------------------
30  *
31  * xxxx000a aaaSnnnn ddddcccc ctttmmmm Register form
32  * xxxx001a aaaSnnnn ddddrrrr bbbbbbbb Immediate form
33  *
34  * 4 bits to select which instruction, one of the following:
35  *
36  * 0000 and 1000 tst
37  * 0001 eor 1001 teq
38  * 0010 sub 1010 cmp
39  * 0011 rsb 1011 cmn
40  * 0100 add 1100 orr
41  * 0101 adc 1101 mov
42  * 0110 sbc 1110 bic
43  * 0111 rsc 1111 mvn
44  *
45  * 1 bit to select Status flag update.
46  *
47  * 1 bit to select Register form or Immediate form.
48  *
49  * 1 bit to select if the PC register is used.
50  *
51  * Each function must also (as always) be repeated for each possible ARM
52  * condition code (15 in total). Total: 1920 functions.
53  *
54  * NOTE: This does not include any special common cases, which might be
55  * nice to have. Examples: comparing against zero, moving common
56  * constants.
57  *
58  * See src/tools/generate_arm_dpi.c for more details.
59  */
60 
61 
62 /*
63  * arg[0] = pointer to rn
64  * arg[1] = int32_t immediate value OR ptr to a reg_func() function
65  * arg[2] = pointer to rd
66  */
67 void A__NAME(struct cpu *cpu, struct arm_instr_call *ic)
68 {
69 #if defined(A__RSB) || defined(A__RSC)
70 #define VAR_A b
71 #define VAR_B a
72 #else
73 #define VAR_A a
74 #define VAR_B b
75 #endif
76 
77 #ifdef A__REG
78  uint32_t (*reg_func)(struct cpu *, struct arm_instr_call *)
79  = (uint32_t (*)(struct cpu *, struct arm_instr_call *))
80  (void *)(size_t)ic->arg[1];
81 #endif
82 
83 #ifdef A__S
84  uint32_t c32;
85 #endif
86 #if defined(A__CMP) || defined(A__CMN) || defined(A__ADC) || defined(A__ADD) \
87  || defined(A__RSC) || defined(A__RSB) || defined(A__SBC) || defined(A__SUB)
88 #ifdef A__S
89  uint64_t
90 #else
91  uint32_t
92 #endif
93 #else
94  uint32_t
95 #endif
96  VAR_B =
97 #ifdef A__REG
98  reg_func(cpu, ic)
99 #else
100 #ifdef A__REGSHORT
101  reg(ic->arg[1])
102 #else
103  ic->arg[1]
104 #endif
105 #endif
106  , c64
107 #if !defined(A__MOV) && !defined(A__MVN)
108  , VAR_A = reg(ic->arg[0])
109 #endif
110  ;
111 
112 #if defined(A__MOV) || defined(A__MVN) || defined(A__TST) || defined(A__TEQ) \
113  || defined(A__AND) || defined(A__BIC) || defined(A__EOR) || defined(A__ORR)
114 #if !defined(A__REG) && !defined(A__REGSHORT) && defined(A__S)
115  /*
116  * TODO: This is not 100% correct, but should work with "recommended"
117  * ARM code: Immediate values larger than 255 are encoded with
118  * rotation. If the S-bit is set, then the carry bit is set to the
119  * highest bit of the operand.
120  *
121  * TODO 2: Perhaps this check should be moved out from here, and into
122  * cpu_arm_instr.c. (More correct, and higher performance.)
123  */
124  if (VAR_B > 255) {
125  if (VAR_B & 0x80000000)
126  cpu->cd.arm.flags |= ARM_F_C;
127  else
128  cpu->cd.arm.flags &= ~ARM_F_C;
129  }
130 #endif
131 #endif
132 
133 
134 #if !defined(A__MOV) && !defined(A__MVN)
135 #ifdef A__PC
136  if (ic->arg[0] == (size_t)&cpu->cd.arm.r[ARM_PC]) {
137  uint32_t low_pc = ((size_t)ic - (size_t)
138  cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
139  VAR_A = cpu->pc & ~((ARM_IC_ENTRIES_PER_PAGE-1)
141  VAR_A += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT) + 8;
142  }
143 #endif
144 #endif
145 
146  /*
147  * Perform the operation:
148  */
149 #if defined(A__AND) || defined(A__TST)
150  c64 = a & b;
151 #endif
152 #if defined(A__EOR) || defined(A__TEQ)
153  c64 = a ^ b;
154 #endif
155 #if defined(A__SUB) || defined(A__CMP) || defined(A__RSB)
156  c64 = a - b;
157 #endif
158 #if defined(A__ADD) || defined(A__CMN)
159  c64 = a + b;
160 #endif
161 #if defined(A__ADC)
162  c64 = a + b + (cpu->cd.arm.flags & ARM_F_C? 1 : 0);
163 #endif
164 #if defined(A__SBC) || defined(A__RSC)
165  b += (cpu->cd.arm.flags & ARM_F_C? 0 : 1);
166  c64 = a - b;
167 #endif
168 #if defined(A__ORR)
169  c64 = a | b;
170 #endif
171 #if defined(A__MOV)
172  c64 = b;
173 #endif
174 #if defined(A__BIC)
175  c64 = a & ~b;
176 #endif
177 #if defined(A__MVN)
178  c64 = ~b;
179 #endif
180 
181 
182 #if defined(A__CMP) || defined(A__CMN) || defined(A__TST) || defined(A__TEQ)
183  /* No write to rd for compare/test. */
184 #else
185 #ifdef A__PC
186  if (ic->arg[2] == (size_t)&cpu->cd.arm.r[ARM_PC]) {
187 #ifndef A__S
188  uint32_t old_pc = cpu->pc;
189  uint32_t mask_within_page = ((ARM_IC_ENTRIES_PER_PAGE-1)
191  ((1 << ARM_INSTR_ALIGNMENT_SHIFT) - 1);
192 #endif
193  cpu->pc = (uint32_t)c64;
194 #ifdef A__S
195  /* Copy the right SPSR into CPSR: */
197  switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {
198  case ARM_MODE_FIQ32:
199  cpu->cd.arm.cpsr = cpu->cd.arm.spsr_fiq; break;
200  case ARM_MODE_IRQ32:
201  cpu->cd.arm.cpsr = cpu->cd.arm.spsr_irq; break;
202  case ARM_MODE_SVC32:
203  cpu->cd.arm.cpsr = cpu->cd.arm.spsr_svc; break;
204  case ARM_MODE_ABT32:
205  cpu->cd.arm.cpsr = cpu->cd.arm.spsr_abt; break;
206  case ARM_MODE_UND32:
207  cpu->cd.arm.cpsr = cpu->cd.arm.spsr_und; break;
208  }
209  cpu->cd.arm.flags = cpu->cd.arm.cpsr >> 28;
211 #else
212  if ((old_pc & ~mask_within_page) ==
213  ((uint32_t)cpu->pc & ~mask_within_page)) {
214  cpu->cd.arm.next_ic = cpu->cd.arm.cur_ic_page +
215  ((cpu->pc & mask_within_page) >>
217  } else
218 #endif
220  return;
221  } else
222  reg(ic->arg[2]) = c64;
223 #else
224  reg(ic->arg[2]) = c64;
225 #endif
226 #endif
227 
228 
229  /*
230  * Status flag update (if the S-bit is set):
231  */
232 #ifdef A__S
233  c32 = c64;
234  cpu->cd.arm.flags
235 #if defined(A__CMP) || defined(A__CMN) || defined(A__ADC) || defined(A__ADD) \
236  || defined(A__RSB) || defined(A__RSC) || defined(A__SBC) || defined(A__SUB)
237  &= ~(ARM_F_V | ARM_F_C | ARM_F_Z | ARM_F_N);
238 #else
239  &= ~(ARM_F_Z | ARM_F_N);
240 #endif
241 
242 #if defined(A__CMP) || defined(A__RSB) || defined(A__SUB) || \
243  defined(A__RSC) || defined(A__SBC)
244  if ((uint32_t)a >= (uint32_t)b)
245  cpu->cd.arm.flags |= ARM_F_C;
246 #else
247 #if defined(A__ADC) || defined(A__ADD) || defined(A__CMN)
248  if (c32 != c64)
249  cpu->cd.arm.flags |= ARM_F_C;
250 #endif
251 #endif
252 
253  if (c32 == 0)
254  cpu->cd.arm.flags |= ARM_F_Z;
255 
256  if ((int32_t)c32 < 0)
257  cpu->cd.arm.flags |= ARM_F_N;
258 
259  /* Calculate the Overflow bit: */
260 #if defined(A__CMP) || defined(A__CMN) || defined(A__ADC) || defined(A__ADD) \
261  || defined(A__RSB) || defined(A__RSC) || defined(A__SBC) || defined(A__SUB)
262  {
263  int v = 0;
264 #if defined(A__ADD) || defined(A__CMN)
265  if (((int32_t)a >= 0 && (int32_t)b >= 0 &&
266  (int32_t)c32 < 0) ||
267  ((int32_t)a < 0 && (int32_t)b < 0 &&
268  (int32_t)c32 >= 0))
269  v = 1;
270 #else
271 #if defined(A__SUB) || defined(A__RSB) || defined(A__CMP) || \
272  defined(A__RSC) || defined(A__SBC)
273  if (((int32_t)a >= 0 && (int32_t)b < 0 &&
274  (int32_t)c32 < 0) ||
275  ((int32_t)a < 0 && (int32_t)b >= 0 &&
276  (int32_t)c32 >= 0))
277  v = 1;
278 #endif
279 #endif
280  if (v)
281  cpu->cd.arm.flags |= ARM_F_V;
282  }
283 #endif
284 #endif /* A__S */
285 
286 #undef VAR_A
287 #undef VAR_B
288 }
289 
290 
291 void A__NAME__eq(struct cpu *cpu, struct arm_instr_call *ic)
292 { if (cpu->cd.arm.flags & ARM_F_Z) A__NAME(cpu, ic); }
293 void A__NAME__ne(struct cpu *cpu, struct arm_instr_call *ic)
294 { if (!(cpu->cd.arm.flags & ARM_F_Z)) A__NAME(cpu, ic); }
295 void A__NAME__cs(struct cpu *cpu, struct arm_instr_call *ic)
296 { if (cpu->cd.arm.flags & ARM_F_C) A__NAME(cpu, ic); }
297 void A__NAME__cc(struct cpu *cpu, struct arm_instr_call *ic)
298 { if (!(cpu->cd.arm.flags & ARM_F_C)) A__NAME(cpu, ic); }
299 void A__NAME__mi(struct cpu *cpu, struct arm_instr_call *ic)
300 { if (cpu->cd.arm.flags & ARM_F_N) A__NAME(cpu, ic); }
301 void A__NAME__pl(struct cpu *cpu, struct arm_instr_call *ic)
302 { if (!(cpu->cd.arm.flags & ARM_F_N)) A__NAME(cpu, ic); }
303 void A__NAME__vs(struct cpu *cpu, struct arm_instr_call *ic)
304 { if (cpu->cd.arm.flags & ARM_F_V) A__NAME(cpu, ic); }
305 void A__NAME__vc(struct cpu *cpu, struct arm_instr_call *ic)
306 { if (!(cpu->cd.arm.flags & ARM_F_V)) A__NAME(cpu, ic); }
307 
308 #ifndef BLAHURG
309 #define BLAHURG
310 extern uint8_t condition_hi[16];
311 extern uint8_t condition_ge[16];
312 extern uint8_t condition_gt[16];
313 #endif
314 
315 void A__NAME__hi(struct cpu *cpu, struct arm_instr_call *ic)
316 { if (condition_hi[cpu->cd.arm.flags]) A__NAME(cpu, ic); }
317 void A__NAME__ls(struct cpu *cpu, struct arm_instr_call *ic)
318 { if (!condition_hi[cpu->cd.arm.flags]) A__NAME(cpu, ic); }
319 void A__NAME__ge(struct cpu *cpu, struct arm_instr_call *ic)
320 { if (condition_ge[cpu->cd.arm.flags]) A__NAME(cpu, ic); }
321 void A__NAME__lt(struct cpu *cpu, struct arm_instr_call *ic)
322 { if (!condition_ge[cpu->cd.arm.flags]) A__NAME(cpu, ic); }
323 void A__NAME__gt(struct cpu *cpu, struct arm_instr_call *ic)
324 { if (condition_gt[cpu->cd.arm.flags]) A__NAME(cpu, ic); }
325 void A__NAME__le(struct cpu *cpu, struct arm_instr_call *ic)
326 { if (!condition_gt[cpu->cd.arm.flags]) A__NAME(cpu, ic); }
327 
void A__NAME__pl(struct cpu *cpu, struct arm_instr_call *ic)
uint32_t spsr_irq
Definition: cpu_arm.h:171
void arm_save_register_bank(struct cpu *cpu)
Definition: cpu_arm.cc:495
#define ARM_MODE_IRQ32
Definition: cpu_arm.h:103
void A__NAME__ne(struct cpu *cpu, struct arm_instr_call *ic)
void A__NAME__gt(struct cpu *cpu, struct arm_instr_call *ic)
#define VAR_A
#define ARM_PC
Definition: cpu_arm.h:56
#define A__CMP
void A__NAME__mi(struct cpu *cpu, struct arm_instr_call *ic)
void A__NAME__lt(struct cpu *cpu, struct arm_instr_call *ic)
struct arm_instr_call * ic
#define A__SUB
union cpu::@1 cd
void A__NAME__cc(struct cpu *cpu, struct arm_instr_call *ic)
#define ARM_MODE_FIQ32
Definition: cpu_arm.h:102
#define ARM_MODE_SVC32
Definition: cpu_arm.h:104
void A__NAME__cs(struct cpu *cpu, struct arm_instr_call *ic)
void A__NAME__ls(struct cpu *cpu, struct arm_instr_call *ic)
uint32_t spsr_fiq
Definition: cpu_arm.h:172
void arm_load_register_bank(struct cpu *cpu)
Definition: cpu_arm.cc:542
uint8_t condition_ge[16]
struct arm_cpu arm
Definition: cpu.h:441
void A__NAME__le(struct cpu *cpu, struct arm_instr_call *ic)
#define reg(x)
#define VAR_B
#define ARM_MODE_UND32
Definition: cpu_arm.h:106
void A__NAME__hi(struct cpu *cpu, struct arm_instr_call *ic)
uint64_t pc
Definition: cpu.h:383
#define ARM_IC_ENTRIES_PER_PAGE
Definition: cpu_arm.h:76
#define ARM_F_V
Definition: cpu_arm.h:85
#define quick_pc_to_pointers(cpu)
#define ARM_INSTR_ALIGNMENT_SHIFT
Definition: cpu_arm.h:75
uint8_t condition_gt[16]
#define A__ADD
void A__NAME__vc(struct cpu *cpu, struct arm_instr_call *ic)
uint32_t spsr_und
Definition: cpu_arm.h:170
#define ARM_F_Z
Definition: cpu_arm.h:83
#define A__CMN
void A__NAME(struct cpu *cpu, struct arm_instr_call *ic)
Definition: cpu.h:326
uint32_t spsr_abt
Definition: cpu_arm.h:169
#define ARM_MODE_ABT32
Definition: cpu_arm.h:105
uint32_t spsr_svc
Definition: cpu_arm.h:168
void A__NAME__ge(struct cpu *cpu, struct arm_instr_call *ic)
void A__NAME__eq(struct cpu *cpu, struct arm_instr_call *ic)
#define A__RSB
#define A__SBC
size_t flags
Definition: cpu_arm.h:166
uint8_t condition_hi[16]
#define ARM_F_N
Definition: cpu_arm.h:82
#define ARM_FLAG_MODE
Definition: cpu_arm.h:96
#define A__ADC
#define ARM_F_C
Definition: cpu_arm.h:84
uint32_t cpsr
Definition: cpu_arm.h:167
void A__NAME__vs(struct cpu *cpu, struct arm_instr_call *ic)
uint32_t r[N_ARM_REGS]
Definition: cpu_arm.h:148
#define A__RSC

Generated on Sun Sep 30 2018 16:05:18 for GXemul by doxygen 1.8.13