• R/O
  • SSH
  • HTTPS

gpsp-kai: Commit


Commit MetaInfo

Revision405 (tree)
Time2008-12-04 09:17:06
Authortakka

Log Message

(empty log message)

Change Summary

Incremental Difference

--- trunk/gpsp-kai-test/src/mips_emit_new.h (revision 404)
+++ trunk/gpsp-kai-test/src/mips_emit_new.h (nonexistent)
@@ -1,2702 +0,0 @@
1-/* unofficial gameplaySP kai
2- *
3- * Copyright (C) 2006 Exophase <exophase@gmail.com>
4- * Copyright (C) 2007 takka <takka@tfact.net>
5- *
6- * This program is free software; you can redistribute it and/or
7- * modify it under the terms of the GNU General Public License as
8- * published by the Free Software Foundation; either version 2 of
9- * the License, or (at your option) any later version.
10- *
11- * This program is distributed in the hope that it will be useful,
12- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14- * General Public License for more details.
15- *
16- * You should have received a copy of the GNU General Public License
17- * along with this program; if not, write to the Free Software
18- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19- */
20-
21-#ifndef MIPS_EMIT_H
22-#define MIPS_EMIT_H
23-
24-
25-u32 mips_update_gba(u32 pc);
26-
27-static u8 cycle_multiply(u32 _rs);
28-
29-// Although these are defined as a function, don't call them as
30-// such (jump to it instead)
31-void mips_indirect_branch_arm(u32 address);
32-void mips_indirect_branch_thumb(u32 address);
33-void mips_indirect_branch_dual(u32 address);
34-
35-u32 execute_read_cpsr(void);
36-u32 execute_read_spsr(void);
37-void execute_swi(u32 pc);
38-
39-u32 execute_spsr_restore(u32 address);
40-void execute_store_cpsr(u32 new_cpsr, u32 store_mask);
41-void execute_store_spsr(u32 new_spsr, u32 store_mask);
42-
43-u32 execute_spsr_restore_body(u32 address);
44-u32 execute_store_cpsr_body(u32 _cpsr, u32 store_mask, u32 address);
45-
46-u32 execute_lsl_flags_reg(u32 value, u32 shift);
47-u32 execute_lsr_flags_reg(u32 value, u32 shift);
48-u32 execute_asr_flags_reg(u32 value, u32 shift);
49-u32 execute_ror_flags_reg(u32 value, u32 shift);
50-
51-void execute_aligned_store32(u32 address, u32 value);
52-u32 execute_aligned_load32(u32 address);
53-
54-// void reg_check();
55-
56-typedef enum
57-{
58- mips_reg_zero, // 0
59- mips_reg_at, // 1
60- mips_reg_v0, // 2
61- mips_reg_v1, // 3
62- mips_reg_a0, // 4
63- mips_reg_a1, // 5
64- mips_reg_a2, // 6
65- mips_reg_a3, // 7
66- mips_reg_t0, // 8
67- mips_reg_t1, // 9
68- mips_reg_t2, // 10
69- mips_reg_t3, // 11
70- mips_reg_t4, // 12
71- mips_reg_t5, // 13
72- mips_reg_t6, // 14
73- mips_reg_t7, // 15
74- mips_reg_s0, // 16
75- mips_reg_s1, // 17
76- mips_reg_s2, // 18
77- mips_reg_s3, // 19
78- mips_reg_s4, // 20
79- mips_reg_s5, // 21
80- mips_reg_s6, // 22
81- mips_reg_s7, // 23
82- mips_reg_t8, // 24
83- mips_reg_t9, // 25
84- mips_reg_k0, // 26
85- mips_reg_k1, // 27
86- mips_reg_gp, // 28
87- mips_reg_sp, // 29
88- mips_reg_fp, // 30
89- mips_reg_ra // 31
90-} MIPS_REG_NUMBER;
91-
92-typedef enum
93-{
94- mips_special_sll = 0x00,
95- mips_special_srl = 0x02,
96- mips_special_sra = 0x03,
97- mips_special_sllv = 0x04,
98- mips_special_srlv = 0x06,
99- mips_special_srav = 0x07,
100- mips_special_jr = 0x08,
101- mips_special_jalr = 0x09,
102- mips_special_movz = 0x0A,
103- mips_special_movn = 0x0B,
104- mips_special_mfhi = 0x10,
105- mips_special_mthi = 0x11,
106- mips_special_mflo = 0x12,
107- mips_special_mtlo = 0x13,
108- mips_special_mult = 0x18,
109- mips_special_multu = 0x19,
110- mips_special_div = 0x1A,
111- mips_special_divu = 0x1B,
112- mips_special_madd = 0x1C,
113- mips_special_maddu = 0x1D,
114- mips_special_add = 0x20,
115- mips_special_addu = 0x21,
116- mips_special_sub = 0x22,
117- mips_special_subu = 0x23,
118- mips_special_and = 0x24,
119- mips_special_or = 0x25,
120- mips_special_xor = 0x26,
121- mips_special_nor = 0x27,
122- mips_special_slt = 0x2A,
123- mips_special_sltu = 0x2B
124-} MIPS_FUNCTION_SPECIAL;
125-
126-typedef enum
127-{
128- mips_special3_ext = 0x00,
129- mips_special3_ins = 0x04,
130- mips_special3_bshfl = 0x20
131-} MIPS_FUNCTION_SPECIAL3;
132-
133-typedef enum
134-{
135- mips_regimm_bltz = 0x00,
136- mips_regimm_bltzal = 0x10
137-} MIPS_FUNCTION_REGIMM;
138-
139-typedef enum
140-{
141- mips_opcode_special = 0x00,
142- mips_opcode_regimm = 0x01,
143- mips_opcode_j = 0x02,
144- mips_opcode_jal = 0x03,
145- mips_opcode_beq = 0x04,
146- mips_opcode_bne = 0x05,
147- mips_opcode_blez = 0x06,
148- mips_opcode_bgtz = 0x07,
149- mips_opcode_addi = 0x08,
150- mips_opcode_addiu = 0x09,
151- mips_opcode_slti = 0x0A,
152- mips_opcode_sltiu = 0x0B,
153- mips_opcode_andi = 0x0C,
154- mips_opcode_ori = 0x0D,
155- mips_opcode_xori = 0x0E,
156- mips_opcode_lui = 0x0F,
157- mips_opcode_llo = 0x18,
158- mips_opcode_lhi = 0x19,
159- mips_opcode_trap = 0x1A,
160- mips_opcode_special2 = 0x1C,
161- mips_opcode_special3 = 0x1F,
162- mips_opcode_lb = 0x20,
163- mips_opcode_lh = 0x21,
164- mips_opcode_lw = 0x23,
165- mips_opcode_lbu = 0x24,
166- mips_opcode_lhu = 0x25,
167- mips_opcode_sb = 0x28,
168- mips_opcode_sh = 0x29,
169- mips_opcode_sw = 0x2B,
170-} MIPS_OPCODE;
171-
172-#define mips_emit_reg(opcode, rs, rt, rd, shift, function) \
173- *((u32 *)translation_ptr) = (mips_opcode_##opcode << 26) | \
174- (rs << 21) | (rt << 16) | (rd << 11) | (shift << 6) | function; \
175- translation_ptr += 4 \
176-
177-#define mips_emit_special(function, rs, rt, rd, shift) \
178- *((u32 *)translation_ptr) = (mips_opcode_special << 26) | \
179- (rs << 21) | (rt << 16) | (rd << 11) | (shift << 6) | \
180- mips_special_##function; \
181- translation_ptr += 4 \
182-
183-#define mips_emit_special3(function, rs, rt, imm_a, imm_b) \
184- *((u32 *)translation_ptr) = (mips_opcode_special3 << 26) | \
185- (rs << 21) | (rt << 16) | (imm_a << 11) | (imm_b << 6) | \
186- mips_special3_##function; \
187- translation_ptr += 4 \
188-
189-#define mips_emit_imm(opcode, rs, rt, immediate) \
190- *((u32 *)translation_ptr) = (mips_opcode_##opcode << 26) | \
191- (rs << 21) | (rt << 16) | (immediate & 0xFFFF); \
192- translation_ptr += 4 \
193-
194-#define mips_emit_regimm(function, rs, immediate) \
195- *((u32 *)translation_ptr) = (mips_opcode_regimm << 26) | \
196- (rs << 21) | (mips_regimm_##function << 16) | (immediate & 0xFFFF); \
197- translation_ptr += 4 \
198-
199-#define mips_emit_jump(opcode, offset) \
200- *((u32 *)translation_ptr) = (mips_opcode_##opcode << 26) | \
201- (offset & 0x3FFFFFF); \
202- translation_ptr += 4 \
203-
204-#define mips_relative_offset(source, offset) \
205- (((u32)offset - ((u32)source + 4)) >> 2) \
206-
207-#define mips_absolute_offset(offset) \
208- ((u32)offset >> 2) \
209-
210-// ADDU rd, rs, rt
211-#define mips_emit_addu(rd, rs, rt) \
212- mips_emit_special(addu, rs, rt, rd, 0) \
213-
214-#define mips_emit_subu(rd, rs, rt) \
215- mips_emit_special(subu, rs, rt, rd, 0) \
216-
217-#define mips_emit_xor(rd, rs, rt) \
218- mips_emit_special(xor, rs, rt, rd, 0) \
219-
220-#define mips_emit_add(rd, rs, rt) \
221- mips_emit_special(add, rs, rt, rd, 0) \
222-
223-#define mips_emit_sub(rd, rs, rt) \
224- mips_emit_special(sub, rs, rt, rd, 0) \
225-
226-#define mips_emit_and(rd, rs, rt) \
227- mips_emit_special(and, rs, rt, rd, 0) \
228-
229-#define mips_emit_or(rd, rs, rt) \
230- mips_emit_special(or, rs, rt, rd, 0) \
231-
232-#define mips_emit_nor(rd, rs, rt) \
233- mips_emit_special(nor, rs, rt, rd, 0) \
234-
235-#define mips_emit_slt(rd, rs, rt) \
236- mips_emit_special(slt, rs, rt, rd, 0) \
237-
238-#define mips_emit_sltu(rd, rs, rt) \
239- mips_emit_special(sltu, rs, rt, rd, 0) \
240-
241-#define mips_emit_sllv(rd, rt, rs) \
242- mips_emit_special(sllv, rs, rt, rd, 0) \
243-
244-#define mips_emit_srlv(rd, rt, rs) \
245- mips_emit_special(srlv, rs, rt, rd, 0) \
246-
247-#define mips_emit_srav(rd, rt, rs) \
248- mips_emit_special(srav, rs, rt, rd, 0) \
249-
250-#define mips_emit_rotrv(rd, rt, rs) \
251- mips_emit_special(srlv, rs, rt, rd, 1) \
252-
253-#define mips_emit_sll(rd, rt, shift) \
254- mips_emit_special(sll, 0, rt, rd, shift) \
255-
256-#define mips_emit_srl(rd, rt, shift) \
257- mips_emit_special(srl, 0, rt, rd, shift) \
258-
259-#define mips_emit_sra(rd, rt, shift) \
260- mips_emit_special(sra, 0, rt, rd, shift) \
261-
262-#define mips_emit_rotr(rd, rt, shift) \
263- mips_emit_special(srl, 1, rt, rd, shift) \
264-
265-#define mips_emit_mfhi(rd) \
266- mips_emit_special(mfhi, 0, 0, rd, 0) \
267-
268-#define mips_emit_mflo(rd) \
269- mips_emit_special(mflo, 0, 0, rd, 0) \
270-
271-#define mips_emit_mthi(rs) \
272- mips_emit_special(mthi, rs, 0, 0, 0) \
273-
274-#define mips_emit_mtlo(rs) \
275- mips_emit_special(mtlo, rs, 0, 0, 0) \
276-
277-#define mips_emit_mult(rs, rt) \
278- mips_emit_special(mult, rs, rt, 0, 0) \
279-
280-#define mips_emit_multu(rs, rt) \
281- mips_emit_special(multu, rs, rt, 0, 0) \
282-
283-#define mips_emit_div(rs, rt) \
284- mips_emit_special(div, rs, rt, 0, 0) \
285-
286-#define mips_emit_divu(rs, rt) \
287- mips_emit_special(divu, rs, rt, 0, 0) \
288-
289-#define mips_emit_madd(rs, rt) \
290- mips_emit_special(madd, rs, rt, 0, 0) \
291-
292-#define mips_emit_maddu(rs, rt) \
293- mips_emit_special(maddu, rs, rt, 0, 0) \
294-
295-#define mips_emit_movn(rd, rs, rt) \
296- mips_emit_special(movn, rs, rt, rd, 0) \
297-
298-#define mips_emit_movz(rd, rs, rt) \
299- mips_emit_special(movz, rs, rt, rd, 0) \
300-
301-#define mips_emit_lb(rt, rs, offset) \
302- mips_emit_imm(lb, rs, rt, offset) \
303-
304-#define mips_emit_lbu(rt, rs, offset) \
305- mips_emit_imm(lbu, rs, rt, offset) \
306-
307-#define mips_emit_lh(rt, rs, offset) \
308- mips_emit_imm(lh, rs, rt, offset) \
309-
310-#define mips_emit_lhu(rt, rs, offset) \
311- mips_emit_imm(lhu, rs, rt, offset) \
312-
313-#define mips_emit_lw(rt, rs, offset) \
314- mips_emit_imm(lw, rs, rt, offset) \
315-
316-#define mips_emit_sb(rt, rs, offset) \
317- mips_emit_imm(sb, rs, rt, offset) \
318-
319-#define mips_emit_sh(rt, rs, offset) \
320- mips_emit_imm(sh, rs, rt, offset) \
321-
322-#define mips_emit_sw(rt, rs, offset) \
323- mips_emit_imm(sw, rs, rt, offset) \
324-
325-#define mips_emit_lui(rt, imm) \
326- mips_emit_imm(lui, 0, rt, imm) \
327-
328-#define mips_emit_addiu(rt, rs, imm) \
329- mips_emit_imm(addiu, rs, rt, imm) \
330-
331-#define mips_emit_xori(rt, rs, imm) \
332- mips_emit_imm(xori, rs, rt, imm) \
333-
334-#define mips_emit_ori(rt, rs, imm) \
335- mips_emit_imm(ori, rs, rt, imm) \
336-
337-#define mips_emit_andi(rt, rs, imm) \
338- mips_emit_imm(andi, rs, rt, imm) \
339-
340-#define mips_emit_slti(rt, rs, imm) \
341- mips_emit_imm(slti, rs, rt, imm) \
342-
343-#define mips_emit_sltiu(rt, rs, imm) \
344- mips_emit_imm(sltiu, rs, rt, imm) \
345-
346-#define mips_emit_ext(rt, rs, pos, size) \
347- mips_emit_special3(ext, rs, rt, (size - 1), pos) \
348-
349-#define mips_emit_ins(rt, rs, pos, size) \
350- mips_emit_special3(ins, rs, rt, (pos + size - 1), pos) \
351-
352-// Breaks down if the backpatch offset is greater than 16bits, take care
353-// when using (should be okay if limited to conditional instructions)
354-
355-#define mips_emit_b_filler(type, rs, rt, writeback_location) \
356- (writeback_location) = translation_ptr; \
357- mips_emit_imm(type, rs, rt, 0) \
358-
359-// The backpatch code for this has to be handled differently than the above
360-
361-#define mips_emit_j_filler(writeback_location) \
362- (writeback_location) = translation_ptr; \
363- mips_emit_jump(j, 0) \
364-
365-#define mips_emit_b(type, rs, rt, offset) \
366- mips_emit_imm(type, rs, rt, offset) \
367-
368-#define mips_emit_j(offset) \
369- mips_emit_jump(j, offset) \
370-
371-#define mips_emit_jal(offset) \
372- mips_emit_jump(jal, offset) \
373-
374-#define mips_emit_jr(rs) \
375- mips_emit_special(jr, rs, 0, 0, 0) \
376-
377-#define mips_emit_bltzal(rs, offset) \
378- mips_emit_regimm(bltzal, rs, offset) \
379-
380-#define mips_emit_nop() \
381- mips_emit_sll(reg_zero, reg_zero, 0) \
382-
383-#define reg_base mips_reg_s0
384-#define reg_cycles mips_reg_s1
385-#define reg_a0 mips_reg_a0
386-#define reg_a1 mips_reg_a1
387-#define reg_a2 mips_reg_a2
388-#define reg_rv mips_reg_v0
389-#define reg_pc mips_reg_s3
390-#define reg_temp mips_reg_at
391-#define reg_zero mips_reg_zero
392-
393-#define reg_n_cache mips_reg_s4
394-#define reg_z_cache mips_reg_s5
395-#define reg_c_cache mips_reg_s6
396-#define reg_v_cache mips_reg_s7
397-
398-#define reg_r0 mips_reg_v1
399-#define reg_r1 mips_reg_a3
400-#define reg_r2 mips_reg_t0
401-#define reg_r3 mips_reg_t1
402-#define reg_r4 mips_reg_t2
403-#define reg_r5 mips_reg_t3
404-#define reg_r6 mips_reg_t4
405-#define reg_r7 mips_reg_t5
406-#define reg_r8 mips_reg_t6
407-#define reg_r9 mips_reg_t7
408-#define reg_r10 mips_reg_s2
409-#define reg_r11 mips_reg_t8
410-#define reg_r12 mips_reg_t9
411-#define reg_r13 mips_reg_gp
412-#define reg_r14 mips_reg_fp
413-
414-// Writing to r15 goes straight to a0, to be chained with other ops
415-
416-u32 arm_to_mips_reg[] =
417-{
418- reg_r0,
419- reg_r1,
420- reg_r2,
421- reg_r3,
422- reg_r4,
423- reg_r5,
424- reg_r6,
425- reg_r7,
426- reg_r8,
427- reg_r9,
428- reg_r10,
429- reg_r11,
430- reg_r12,
431- reg_r13,
432- reg_r14,
433- reg_a0,
434- reg_a1,
435- reg_a2,
436- reg_temp
437-};
438-
439-#define arm_reg_a0 15
440-#define arm_reg_a1 16
441-#define arm_reg_a2 17
442-#define arm_reg_temp 18
443-
444-#define generate_load_reg(ireg, reg_index) \
445- mips_emit_addu(ireg, arm_to_mips_reg[reg_index], reg_zero) \
446-
447-#define generate_load_imm(ireg, imm) \
448- if(((s32)imm >= -32768) && ((s32)imm <= 32767)) \
449- { \
450- mips_emit_addiu(ireg, reg_zero, imm); \
451- } \
452- else \
453- { \
454- if(((u32)imm >> 16) == 0x0000) \
455- { \
456- mips_emit_ori(ireg, reg_zero, imm); \
457- } \
458- else \
459- { \
460- mips_emit_lui(ireg, imm >> 16); \
461- \
462- if(((u32)imm & 0x0000FFFF) != 0x00000000) \
463- { \
464- mips_emit_ori(ireg, ireg, imm & 0xFFFF); \
465- } \
466- } \
467- } \
468-
469-#define generate_load_pc(ireg, new_pc) \
470-{ \
471- s32 pc_delta = new_pc - stored_pc; \
472- if((pc_delta >= -32768) && (pc_delta <= 32767)) \
473- { \
474- mips_emit_addiu(ireg, reg_pc, pc_delta); \
475- } \
476- else \
477- { \
478- generate_load_imm(ireg, new_pc); \
479- } \
480-} \
481-
482-#define generate_store_reg(ireg, reg_index) \
483- mips_emit_addu(arm_to_mips_reg[reg_index], ireg, reg_zero) \
484-
485-#define generate_shift_left(ireg, imm) \
486- mips_emit_sll(ireg, ireg, imm) \
487-
488-#define generate_shift_right(ireg, imm) \
489- mips_emit_srl(ireg, ireg, imm) \
490-
491-#define generate_shift_right_arithmetic(ireg, imm) \
492- mips_emit_sra(ireg, ireg, imm) \
493-
494-#define generate_rotate_right(ireg, imm) \
495- mips_emit_rotr(ireg, ireg, imm) \
496-
497-#define generate_add(ireg_dest, ireg_src) \
498- mips_emit_addu(ireg_dest, ireg_dest, ireg_src) \
499-
500-#define generate_sub(ireg_dest, ireg_src) \
501- mips_emit_subu(ireg_dest, ireg_dest, ireg_src) \
502-
503-#define generate_or(ireg_dest, ireg_src) \
504- mips_emit_or(ireg_dest, ireg_dest, ireg_src) \
505-
506-#define generate_xor(ireg_dest, ireg_src) \
507- mips_emit_xor(ireg_dest, ireg_dest, ireg_src) \
508-
509-#define generate_alu_imm(imm_type, reg_type, ireg_dest, ireg_src, imm) \
510- if(((s32)imm >= -32768) && ((s32)imm <= 32767)) \
511- { \
512- mips_emit_##imm_type(ireg_dest, ireg_src, imm); \
513- } \
514- else \
515- { \
516- generate_load_imm(reg_temp, imm); \
517- mips_emit_##reg_type(ireg_dest, ireg_src, reg_temp); \
518- } \
519-
520-#define generate_alu_immu(imm_type, reg_type, ireg_dest, ireg_src, imm) \
521- if(((u32)imm >= 0) && ((u32)imm <= 65535)) \
522- { \
523- mips_emit_##imm_type(ireg_dest, ireg_src, imm); \
524- } \
525- else \
526- { \
527- generate_load_imm(reg_temp, imm); \
528- mips_emit_##reg_type(ireg_dest, ireg_src, reg_temp); \
529- } \
530-
531-#define generate_add_imm(ireg, imm) \
532- generate_alu_imm(addiu, add, ireg, ireg, imm) \
533-
534-#define generate_sub_imm(ireg, imm) \
535- generate_alu_imm(addiu, add, ireg, ireg, -imm) \
536-
537-#define generate_xor_imm(ireg, imm) \
538- generate_alu_immu(xori, xor, ireg, ireg, imm) \
539-
540-#define generate_add_reg_reg_imm(ireg_dest, ireg_src, imm) \
541- generate_alu_imm(addiu, add, ireg_dest, ireg_src, imm) \
542-
543-#define generate_and_imm(ireg, imm) \
544- generate_alu_immu(andi, and, ireg, ireg, imm) \
545-
546-#define generate_mov(ireg_dest, ireg_src) \
547- mips_emit_addu(ireg_dest, ireg_src, reg_zero) \
548-
549-#define generate_multiply_s64() \
550- mips_emit_mult(arm_to_mips_reg[rm], arm_to_mips_reg[rs]) \
551-
552-#define generate_multiply_u64() \
553- mips_emit_multu(arm_to_mips_reg[rm], arm_to_mips_reg[rs]) \
554-
555-#define generate_multiply_s64_add() \
556- mips_emit_madd(arm_to_mips_reg[rm], arm_to_mips_reg[rs]) \
557-
558-#define generate_multiply_u64_add() \
559- mips_emit_maddu(arm_to_mips_reg[rm], arm_to_mips_reg[rs]) \
560-
561-#define generate_function_call(function_location) \
562- mips_emit_jal(mips_absolute_offset(function_location)); \
563- mips_emit_nop() \
564-
565-#define generate_function_call_swap_delay(function_location) \
566-{ \
567- u32 delay_instruction = ADDRESS32(translation_ptr, -4); \
568- translation_ptr -= 4; \
569- mips_emit_jal(mips_absolute_offset(function_location)); \
570- ADDRESS32(translation_ptr, 0) = delay_instruction; \
571- translation_ptr += 4; \
572-} \
573-
574-#define generate_swap_delay() \
575-{ \
576- u32 delay_instruction = ADDRESS32(translation_ptr, -8); \
577- u32 branch_instruction = ADDRESS32(translation_ptr, -4); \
578- branch_instruction = (branch_instruction & 0xFFFF0000) | \
579- (((branch_instruction & 0x0000FFFF) + 1) & 0x0000FFFF); \
580- ADDRESS32(translation_ptr, -8) = branch_instruction; \
581- ADDRESS32(translation_ptr, -4) = delay_instruction; \
582-} \
583-
584-#define generate_cycle_update() \
585- if(cycle_count != 0) \
586- { \
587- mips_emit_addiu(reg_cycles, reg_cycles, -cycle_count); \
588- cycle_count = 0; \
589- } \
590-
591-#define generate_cycle_update_force() \
592- mips_emit_addiu(reg_cycles, reg_cycles, -cycle_count); \
593- cycle_count = 0 \
594-
595-#define generate_branch_patch_conditional(dest, offset) \
596- *((u16 *)(dest)) = mips_relative_offset(dest, offset) \
597-
598-#define generate_branch_patch_unconditional(dest, offset) \
599- *((u32 *)(dest)) = (mips_opcode_j << 26) | \
600- ((mips_absolute_offset(offset)) & 0x3FFFFFF) \
601-
602-#define generate_branch_no_cycle_update(writeback_location, new_pc) \
603- { \
604- u8 i; \
605- u8 flag = 0; \
606- \
607- for( i = 0; i < idle_loop_targets; i++) \
608- { \
609- if(pc == idle_loop_target_pc[i]) \
610- { \
611- flag = 1; \
612- } \
613- } \
614- \
615- if(flag == 1) \
616- { \
617- generate_load_pc(reg_a0, new_pc); \
618- generate_function_call_swap_delay(mips_update_gba); \
619- mips_emit_j_filler(writeback_location); \
620- mips_emit_nop(); \
621- } \
622- else \
623- { \
624- generate_load_pc(reg_a0, new_pc); \
625- mips_emit_bltzal(reg_cycles, \
626- mips_relative_offset(translation_ptr, update_trampoline)); \
627- generate_swap_delay(); \
628- mips_emit_j_filler(writeback_location); \
629- mips_emit_nop(); \
630- } \
631- } \
632-
633-#define generate_branch_cycle_update(writeback_location, new_pc) \
634- generate_cycle_update(); \
635- generate_branch_no_cycle_update(writeback_location, new_pc) \
636-
637-#define generate_conditional_branch(ireg_a, ireg_b, type, writeback_location) \
638- generate_branch_filler_##type(ireg_a, ireg_b, writeback_location) \
639-
640-// a0 holds the destination
641-
642-#define generate_indirect_branch_cycle_update(type) \
643- mips_emit_j(mips_absolute_offset(mips_indirect_branch_##type)); \
644- generate_cycle_update_force() \
645-
646-#define generate_indirect_branch_no_cycle_update(type) \
647- mips_emit_j(mips_absolute_offset(mips_indirect_branch_##type)); \
648- mips_emit_nop() \
649-
650-#define generate_block_prologue() \
651- update_trampoline = translation_ptr; \
652- __asm__ \
653- ( \
654- "cache 8, 0(%0)\n" \
655- "cache 8, 0(%0)" : : "r"(translation_ptr) \
656- ); \
657- \
658- mips_emit_j(mips_absolute_offset(mips_update_gba)); \
659- mips_emit_nop(); \
660- generate_load_imm(reg_pc, stored_pc) \
661-
662-#define translate_invalidate_dcache() \
663- sceKernelDcacheWritebackAll() \
664-
665-#define block_prologue_size 8
666-
667-#define check_generate_n_flag \
668- (flag_status & 0x08) \
669-
670-#define check_generate_z_flag \
671- (flag_status & 0x04) \
672-
673-#define check_generate_c_flag \
674- (flag_status & 0x02) \
675-
676-#define check_generate_v_flag \
677- (flag_status & 0x01) \
678-
679-#define generate_load_reg_pc(ireg, reg_index, pc_offset) \
680- if(reg_index == REG_PC) \
681- { \
682- generate_load_pc(ireg, (pc + pc_offset)); \
683- } \
684- else \
685- { \
686- generate_load_reg(ireg, reg_index); \
687- } \
688-
689-#define check_load_reg_pc(arm_reg, reg_index, pc_offset) \
690- if(reg_index == REG_PC) \
691- { \
692- reg_index = arm_reg; \
693- generate_load_pc(arm_to_mips_reg[arm_reg], (pc + pc_offset)); \
694- } \
695-
696-#define check_store_reg_pc_no_flags(reg_index) \
697- if(reg_index == REG_PC) \
698- { \
699- generate_indirect_branch_arm(); \
700- } \
701-
702-#define check_store_reg_pc_flags(reg_index) \
703- if(reg_index == REG_PC) \
704- { \
705- generate_function_call(execute_spsr_restore); \
706- generate_indirect_branch_dual(); \
707- } \
708-
709-#define generate_shift_imm_lsl_no_flags(arm_reg, _rm, _shift) \
710- check_load_reg_pc(arm_reg, _rm, 8); \
711- if(_shift != 0) \
712- { \
713- mips_emit_sll(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], _shift); \
714- _rm = arm_reg; \
715- } \
716-
717-#define generate_shift_imm_lsr_no_flags(arm_reg, _rm, _shift) \
718- if(_shift != 0) \
719- { \
720- check_load_reg_pc(arm_reg, _rm, 8); \
721- mips_emit_srl(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], _shift); \
722- } \
723- else \
724- { \
725- mips_emit_addu(arm_to_mips_reg[arm_reg], reg_zero, reg_zero); \
726- } \
727- _rm = arm_reg \
728-
729-#define generate_shift_imm_asr_no_flags(arm_reg, _rm, _shift) \
730- check_load_reg_pc(arm_reg, _rm, 8); \
731- if(_shift != 0) \
732- { \
733- mips_emit_sra(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], _shift); \
734- } \
735- else \
736- { \
737- mips_emit_sra(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], 31); \
738- } \
739- _rm = arm_reg \
740-
741-#define generate_shift_imm_ror_no_flags(arm_reg, _rm, _shift) \
742- check_load_reg_pc(arm_reg, _rm, 8); \
743- if(_shift != 0) \
744- { \
745- mips_emit_rotr(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], _shift); \
746- } \
747- else \
748- { \
749- mips_emit_srl(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], 1); \
750- mips_emit_ins(arm_to_mips_reg[arm_reg], reg_c_cache, 31, 1); \
751- } \
752- _rm = arm_reg \
753-
754-#define generate_shift_imm_lsl_flags(arm_reg, _rm, _shift) \
755- check_load_reg_pc(arm_reg, _rm, 8); \
756- if(_shift != 0) \
757- { \
758- mips_emit_ext(reg_c_cache, arm_to_mips_reg[_rm], (32 - _shift), 1); \
759- mips_emit_sll(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], _shift); \
760- _rm = arm_reg; \
761- } \
762-
763-#define generate_shift_imm_lsr_flags(arm_reg, _rm, _shift) \
764- check_load_reg_pc(arm_reg, _rm, 8); \
765- if(_shift != 0) \
766- { \
767- mips_emit_ext(reg_c_cache, arm_to_mips_reg[_rm], (_shift - 1), 1); \
768- mips_emit_srl(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], _shift); \
769- } \
770- else \
771- { \
772- mips_emit_srl(reg_c_cache, arm_to_mips_reg[_rm], 31); \
773- mips_emit_addu(arm_to_mips_reg[arm_reg], reg_zero, reg_zero); \
774- } \
775- _rm = arm_reg \
776-
777-#define generate_shift_imm_asr_flags(arm_reg, _rm, _shift) \
778- check_load_reg_pc(arm_reg, _rm, 8); \
779- if(_shift != 0) \
780- { \
781- mips_emit_ext(reg_c_cache, arm_to_mips_reg[_rm], (_shift - 1), 1); \
782- mips_emit_sra(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], _shift); \
783- } \
784- else \
785- { \
786- mips_emit_sra(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], 31); \
787- mips_emit_andi(reg_c_cache, arm_to_mips_reg[arm_reg], 1); \
788- } \
789- _rm = arm_reg \
790-
791-#define generate_shift_imm_ror_flags(arm_reg, _rm, _shift) \
792- check_load_reg_pc(arm_reg, _rm, 8); \
793- if(_shift != 0) \
794- { \
795- mips_emit_ext(reg_c_cache, arm_to_mips_reg[_rm], (_shift - 1), 1); \
796- mips_emit_rotr(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], _shift); \
797- } \
798- else \
799- { \
800- mips_emit_andi(reg_temp, arm_to_mips_reg[_rm], 1); \
801- mips_emit_srl(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], 1); \
802- mips_emit_ins(arm_to_mips_reg[arm_reg], reg_c_cache, 31, 1); \
803- mips_emit_addu(reg_c_cache, reg_temp, reg_zero); \
804- } \
805- _rm = arm_reg \
806-
807-#define generate_shift_reg_lsl_no_flags(_rm, _rs) \
808- mips_emit_sltiu(reg_temp, arm_to_mips_reg[_rs], 32); \
809- mips_emit_sllv(reg_a0, arm_to_mips_reg[_rm], arm_to_mips_reg[_rs]); \
810- mips_emit_movz(reg_a0, reg_zero, reg_temp) \
811-
812-#define generate_shift_reg_lsr_no_flags(_rm, _rs) \
813- mips_emit_sltiu(reg_temp, arm_to_mips_reg[_rs], 32); \
814- mips_emit_srlv(reg_a0, arm_to_mips_reg[_rm], arm_to_mips_reg[_rs]); \
815- mips_emit_movz(reg_a0, reg_zero, reg_temp) \
816-
817-#define generate_shift_reg_asr_no_flags(_rm, _rs) \
818- mips_emit_sltiu(reg_temp, arm_to_mips_reg[_rs], 32); \
819- mips_emit_b(bne, reg_temp, reg_zero, 2); \
820- mips_emit_srav(reg_a0, arm_to_mips_reg[_rm], arm_to_mips_reg[_rs]); \
821- mips_emit_sra(reg_a0, reg_a0, 31) \
822-
823-#define generate_shift_reg_ror_no_flags(_rm, _rs) \
824- mips_emit_rotrv(reg_a0, arm_to_mips_reg[_rm], arm_to_mips_reg[_rs]) \
825-
826-#define generate_shift_reg_lsl_flags(_rm, _rs) \
827- generate_load_reg_pc(reg_a0, _rm, 12); \
828- generate_load_reg_pc(reg_a1, _rs, 8); \
829- generate_function_call_swap_delay(execute_lsl_flags_reg) \
830-
831-#define generate_shift_reg_lsr_flags(_rm, _rs) \
832- generate_load_reg_pc(reg_a0, _rm, 12); \
833- generate_load_reg_pc(reg_a1, _rs, 8); \
834- generate_function_call_swap_delay(execute_lsr_flags_reg) \
835-
836-#define generate_shift_reg_asr_flags(_rm, _rs) \
837- generate_load_reg_pc(reg_a0, _rm, 12); \
838- generate_load_reg_pc(reg_a1, _rs, 8); \
839- generate_function_call_swap_delay(execute_asr_flags_reg) \
840-
841-#define generate_shift_reg_ror_flags(_rm, _rs) \
842- mips_emit_b(beq, arm_to_mips_reg[_rs], reg_zero, 3); \
843- mips_emit_addiu(reg_temp, arm_to_mips_reg[_rs], -1); \
844- mips_emit_srlv(reg_temp, arm_to_mips_reg[_rm], reg_temp); \
845- mips_emit_andi(reg_c_cache, reg_temp, 1); \
846- mips_emit_rotrv(reg_a0, arm_to_mips_reg[_rm], arm_to_mips_reg[_rs]) \
847-
848-#define generate_shift_imm(arm_reg, name, flags_op) \
849- u32 shift = ((opcode >> 7) & 0x1F); \
850- generate_shift_imm_##name##_##flags_op(arm_reg, rm, shift) \
851-
852-#define generate_shift_reg(arm_reg, name, flags_op) \
853- u32 rs = ((opcode >> 8) & 0x0F); \
854- generate_shift_reg_##name##_##flags_op(rm, rs); \
855- rm = arm_reg \
856-
857-// Made functions due to the macro expansion getting too large.
858-// Returns a new rm if it redirects it (which will happen on most of these
859-// cases)
860-
861-#define generate_load_rm_sh_builder(flags_op) \
862-u32 generate_load_rm_sh_##flags_op(u32 rm) \
863-{ \
864- switch((opcode >> 4) & 0x07) \
865- { \
866- /* LSL imm */ \
867- case 0x0: \
868- { \
869- generate_shift_imm(arm_reg_a0, lsl, flags_op); \
870- break; \
871- } \
872- \
873- /* LSL reg */ \
874- case 0x1: \
875- { \
876- generate_shift_reg(arm_reg_a0, lsl, flags_op); \
877- break; \
878- } \
879- \
880- /* LSR imm */ \
881- case 0x2: \
882- { \
883- generate_shift_imm(arm_reg_a0, lsr, flags_op); \
884- break; \
885- } \
886- \
887- /* LSR reg */ \
888- case 0x3: \
889- { \
890- generate_shift_reg(arm_reg_a0, lsr, flags_op); \
891- break; \
892- } \
893- \
894- /* ASR imm */ \
895- case 0x4: \
896- { \
897- generate_shift_imm(arm_reg_a0, asr, flags_op); \
898- break; \
899- } \
900- \
901- /* ASR reg */ \
902- case 0x5: \
903- { \
904- generate_shift_reg(arm_reg_a0, asr, flags_op); \
905- break; \
906- } \
907- \
908- /* ROR imm */ \
909- case 0x6: \
910- { \
911- generate_shift_imm(arm_reg_a0, ror, flags_op); \
912- break; \
913- } \
914- \
915- /* ROR reg */ \
916- case 0x7: \
917- { \
918- generate_shift_reg(arm_reg_a0, ror, flags_op); \
919- break; \
920- } \
921- } \
922- \
923- return rm; \
924-} \
925-
926-#define read_memory_constant_u8(address) \
927- read_memory8(address) \
928-
929-#define read_memory_constant_u16(address) \
930- read_memory16(address) \
931-
932-#define read_memory_constant_u32(address) \
933- read_memory32(address) \
934-
935-#define read_memory_constant_s8(address) \
936- (s8)read_memory8(address) \
937-
938-#define read_memory_constant_s16(address) \
939- (s16)read_memory16_signed(address) \
940-
941-#define generate_load_memory_u8(ireg, offset) \
942- mips_emit_lbu(ireg, ireg, offset) \
943-
944-#define generate_load_memory_u16(ireg, offset) \
945- mips_emit_lhu(ireg, ireg, offset) \
946-
947-#define generate_load_memory_u32(ireg, offset) \
948- mips_emit_lw(ireg, ireg, offset) \
949-
950-#define generate_load_memory_s8(ireg, offset) \
951- mips_emit_lb(ireg, ireg, offset) \
952-
953-#define generate_load_memory_s16(ireg, offset) \
954- mips_emit_lh(ireg, ireg, offset) \
955-
956-#define generate_load_memory(type, ireg, address) \
957-{ \
958- u32 _address = (u32)(address); \
959- u32 _address_hi = (_address + 0x8000) >> 16; \
960- generate_load_imm(ireg, address); \
961- mips_emit_lui(ireg, _address_hi >> 16); \
962- generate_load_memory_##type(ireg, _address - (_address_hi << 16)); \
963-} \
964-
965-#define generate_known_address_load_builder(type) \
966- u32 generate_known_address_load_##type(u32 rd, u32 address) \
967- { \
968- switch(address >> 24) \
969- { \
970- /* Read from the BIOS ROM, can be converted to an immediate load. \
971- Only really possible to do this from the BIOS but should be okay \
972- to allow it everywhere */ \
973- case 0x00: \
974- u32 imm = read_memory_constant_##type(address); \
975- generate_load_imm(arm_to_mips_reg[rd], imm); \
976- return 1; \
977- \
978- /* Read from RAM, can be converted to a load */ \
979- case 0x02: \
980- generate_load_memory(type, arm_to_mips_reg[rd], (u8 *)ewram + \
981- (address & 0x7FFF) + ((address & 0x38000) * 2) + 0x8000); \
982- return 1; \
983- \
984- case 0x03: \
985- generate_load_memory(type, arm_to_mips_reg[rd], (u8 *)iwram + \
986- (address & 0x7FFF) + 0x8000); \
987- return 1; \
988- \
989- /* Read from gamepak ROM, this has to be an immediate load because \
990- it might not actually be in memory anymore when we get to it. */ \
991- case 0x08: \
992- u32 imm = read_memory_constant_##type(address); \
993- generate_load_imm(arm_to_mips_reg[rd], imm); \
994- return 1; \
995- \
996- default: \
997- return 0; \
998- } \
999- } \
1000-
1001-#define generate_block_extra_vars() \
1002- u32 stored_pc = pc; \
1003- u8 *update_trampoline \
1004-
1005-#define generate_block_extra_vars_arm() \
1006- generate_block_extra_vars(); \
1007- generate_load_rm_sh_builder(flags); \
1008- generate_load_rm_sh_builder(no_flags); \
1009- \
1010-/* generate_known_address_load_builder(u8); \
1011- generate_known_address_load_builder(u16); \
1012- generate_known_address_load_builder(u32); \
1013- generate_known_address_load_builder(s8); \
1014- generate_known_address_load_builder(s16); */ \
1015- \
1016- u32 generate_load_offset_sh(u32 rm) \
1017- { \
1018- switch((opcode >> 5) & 0x03) \
1019- { \
1020- /* LSL imm */ \
1021- case 0x0: \
1022- { \
1023- generate_shift_imm(arm_reg_a1, lsl, no_flags); \
1024- break; \
1025- } \
1026- \
1027- /* LSR imm */ \
1028- case 0x1: \
1029- { \
1030- generate_shift_imm(arm_reg_a1, lsr, no_flags); \
1031- break; \
1032- } \
1033- \
1034- /* ASR imm */ \
1035- case 0x2: \
1036- { \
1037- generate_shift_imm(arm_reg_a1, asr, no_flags); \
1038- break; \
1039- } \
1040- \
1041- /* ROR imm */ \
1042- case 0x3: \
1043- { \
1044- generate_shift_imm(arm_reg_a1, ror, no_flags); \
1045- break; \
1046- } \
1047- } \
1048- \
1049- return rm; \
1050- } \
1051- \
1052- void generate_indirect_branch_arm() \
1053- { \
1054- if(condition == 0x0E) \
1055- { \
1056- generate_indirect_branch_cycle_update(arm); \
1057- } \
1058- else \
1059- { \
1060- generate_indirect_branch_no_cycle_update(arm); \
1061- } \
1062- } \
1063- \
1064- void generate_indirect_branch_dual() \
1065- { \
1066- if(condition == 0x0E) \
1067- { \
1068- generate_indirect_branch_cycle_update(dual); \
1069- } \
1070- else \
1071- { \
1072- generate_indirect_branch_no_cycle_update(dual); \
1073- } \
1074- } \
1075-
1076-#define generate_block_extra_vars_thumb() \
1077- generate_block_extra_vars() \
1078-
1079-// It should be okay to still generate result flags, spsr will overwrite them.
1080-// This is pretty infrequent (returning from interrupt handlers, et al) so
1081-// probably not worth optimizing for.
1082-
1083-u32 execute_spsr_restore_body(u32 address)
1084-{
1085- set_cpu_mode(cpu_modes[reg[REG_CPSR] & 0x1F]);
1086-
1087- if((io_registers[REG_IE] & io_registers[REG_IF]) &&
1088- io_registers[REG_IME] && ((reg[REG_CPSR] & 0x80) == 0))
1089- {
1090- reg_mode[MODE_IRQ][6] = address + 4;
1091- spsr[MODE_IRQ] = reg[REG_CPSR];
1092- reg[REG_CPSR] = (reg[REG_CPSR] & ~0xFF) | 0xD2;
1093- set_cpu_mode(MODE_IRQ);
1094-
1095- address = 0x00000018;
1096- }
1097-
1098- if(reg[REG_CPSR] & 0x20)
1099- {
1100- address |= 0x01;
1101- }
1102-
1103- return address;
1104-}
1105-
1106-typedef enum
1107-{
1108- CONDITION_TRUE,
1109- CONDITION_FALSE,
1110- CONDITION_EQUAL,
1111- CONDITION_NOT_EQUAL
1112-} CONDITION_CHECK_TYPE;
1113-
1114-
1115-#define generate_condition_eq() \
1116- mips_emit_b_filler(beq, reg_z_cache, reg_zero, backpatch_address); \
1117- generate_cycle_update_force() \
1118-
1119-#define generate_condition_ne() \
1120- mips_emit_b_filler(bne, reg_z_cache, reg_zero, backpatch_address); \
1121- generate_cycle_update_force() \
1122-
1123-#define generate_condition_cs() \
1124- mips_emit_b_filler(beq, reg_c_cache, reg_zero, backpatch_address); \
1125- generate_cycle_update_force() \
1126-
1127-#define generate_condition_cc() \
1128- mips_emit_b_filler(bne, reg_c_cache, reg_zero, backpatch_address); \
1129- generate_cycle_update_force() \
1130-
1131-#define generate_condition_mi() \
1132- mips_emit_b_filler(beq, reg_n_cache, reg_zero, backpatch_address); \
1133- generate_cycle_update_force() \
1134-
1135-#define generate_condition_pl() \
1136- mips_emit_b_filler(bne, reg_n_cache, reg_zero, backpatch_address); \
1137- generate_cycle_update_force() \
1138-
1139-#define generate_condition_vs() \
1140- mips_emit_b_filler(beq, reg_v_cache, reg_zero, backpatch_address); \
1141- generate_cycle_update_force() \
1142-
1143-#define generate_condition_vc() \
1144- mips_emit_b_filler(bne, reg_v_cache, reg_zero, backpatch_address); \
1145- generate_cycle_update_force() \
1146-
1147-#define generate_condition_hi() \
1148- mips_emit_xori(reg_temp, reg_c_cache, 1); \
1149- mips_emit_or(reg_temp, reg_temp, reg_z_cache); \
1150- mips_emit_b_filler(bne, reg_temp, reg_zero, backpatch_address); \
1151- generate_cycle_update_force() \
1152-
1153-#define generate_condition_ls() \
1154- mips_emit_xori(reg_temp, reg_c_cache, 1); \
1155- mips_emit_or(reg_temp, reg_temp, reg_z_cache); \
1156- mips_emit_b_filler(beq, reg_temp, reg_zero, backpatch_address); \
1157- generate_cycle_update_force() \
1158-
1159-#define generate_condition_ge() \
1160- mips_emit_b_filler(bne, reg_n_cache, reg_v_cache, backpatch_address); \
1161- generate_cycle_update_force() \
1162-
1163-#define generate_condition_lt() \
1164- mips_emit_b_filler(beq, reg_n_cache, reg_v_cache, backpatch_address); \
1165- generate_cycle_update_force() \
1166-
1167-#define generate_condition_gt() \
1168- mips_emit_xor(reg_temp, reg_n_cache, reg_v_cache); \
1169- mips_emit_or(reg_temp, reg_temp, reg_z_cache); \
1170- mips_emit_b_filler(bne, reg_temp, reg_zero, backpatch_address); \
1171- generate_cycle_update_force() \
1172-
1173-#define generate_condition_le() \
1174- mips_emit_xor(reg_temp, reg_n_cache, reg_v_cache); \
1175- mips_emit_or(reg_temp, reg_temp, reg_z_cache); \
1176- mips_emit_b_filler(beq, reg_temp, reg_zero, backpatch_address); \
1177- generate_cycle_update_force() \
1178-
1179-#define generate_condition() \
1180- switch(condition) \
1181- { \
1182- case 0x0: \
1183- generate_condition_eq(); \
1184- break; \
1185- \
1186- case 0x1: \
1187- generate_condition_ne(); \
1188- break; \
1189- \
1190- case 0x2: \
1191- generate_condition_cs(); \
1192- break; \
1193- \
1194- case 0x3: \
1195- generate_condition_cc(); \
1196- break; \
1197- \
1198- case 0x4: \
1199- generate_condition_mi(); \
1200- break; \
1201- \
1202- case 0x5: \
1203- generate_condition_pl(); \
1204- break; \
1205- \
1206- case 0x6: \
1207- generate_condition_vs(); \
1208- break; \
1209- \
1210- case 0x7: \
1211- generate_condition_vc(); \
1212- break; \
1213- \
1214- case 0x8: \
1215- generate_condition_hi(); \
1216- break; \
1217- \
1218- case 0x9: \
1219- generate_condition_ls(); \
1220- break; \
1221- \
1222- case 0xA: \
1223- generate_condition_ge(); \
1224- break; \
1225- \
1226- case 0xB: \
1227- generate_condition_lt(); \
1228- break; \
1229- \
1230- case 0xC: \
1231- generate_condition_gt(); \
1232- break; \
1233- \
1234- case 0xD: \
1235- generate_condition_le(); \
1236- break; \
1237- \
1238- case 0xE: \
1239- break; \
1240- \
1241- case 0xF: \
1242- break; \
1243- } \
1244-
1245-#define generate_branch() \
1246-{ \
1247- if(condition == 0x0E) \
1248- { \
1249- generate_branch_cycle_update( \
1250- block_exits[block_exit_position].branch_source, \
1251- block_exits[block_exit_position].branch_target); \
1252- } \
1253- else \
1254- { \
1255- generate_branch_no_cycle_update( \
1256- block_exits[block_exit_position].branch_source, \
1257- block_exits[block_exit_position].branch_target); \
1258- } \
1259- block_exit_position++; \
1260-} \
1261-
1262-#define generate_op_and_reg(_rd, _rn, _rm) \
1263- mips_emit_and(_rd, _rn, _rm) \
1264-
1265-#define generate_op_orr_reg(_rd, _rn, _rm) \
1266- mips_emit_or(_rd, _rn, _rm) \
1267-
1268-#define generate_op_eor_reg(_rd, _rn, _rm) \
1269- mips_emit_xor(_rd, _rn, _rm) \
1270-
1271-#define generate_op_bic_reg(_rd, _rn, _rm) \
1272- mips_emit_nor(reg_temp, _rm, reg_zero); \
1273- mips_emit_and(_rd, _rn, reg_temp) \
1274-
1275-#define generate_op_sub_reg(_rd, _rn, _rm) \
1276- mips_emit_subu(_rd, _rn, _rm) \
1277-
1278-#define generate_op_rsb_reg(_rd, _rn, _rm) \
1279- mips_emit_subu(_rd, _rm, _rn) \
1280-
1281-/* SBC Rd = Rn - <Oprnd> - NOT(Carry) */
1282-#define generate_op_sbc_reg(_rd, _rn, _rm) \
1283- mips_emit_subu(_rd, _rn, _rm); \
1284- mips_emit_xori(reg_temp, reg_c_cache, 1); \
1285- mips_emit_subu(_rd, _rd, reg_temp) \
1286-
1287-/* RSC Rd = <Oprnd> - Rn - NOT(Carry) */
1288-#define generate_op_rsc_reg(_rd, _rn, _rm) \
1289- mips_emit_subu(_rd, _rm, _rn); \
1290- mips_emit_xori(reg_temp, reg_c_cache, 1); \
1291- mips_emit_subu(_rd, _rd, reg_temp) \
1292-
1293-#define generate_op_add_reg(_rd, _rn, _rm) \
1294- mips_emit_addu(_rd, _rn, _rm) \
1295-
1296-#define generate_op_adc_reg(_rd, _rn, _rm) \
1297- mips_emit_addu(reg_temp, _rm, reg_c_cache); \
1298- mips_emit_addu(_rd, _rn, reg_temp) \
1299-
1300-#define generate_op_mov_reg(_rd, _rn, _rm) \
1301- mips_emit_addu(_rd, _rm, reg_zero) \
1302-
1303-#define generate_op_mvn_reg(_rd, _rn, _rm) \
1304- mips_emit_nor(_rd, _rm, reg_zero) \
1305-
1306-#define generate_op_imm_wrapper(name, _rd, _rn) \
1307- if(imm != 0) \
1308- { \
1309- generate_load_imm(reg_a0, imm); \
1310- generate_op_##name##_reg(_rd, _rn, reg_a0); \
1311- } \
1312- else \
1313- { \
1314- generate_op_##name##_reg(_rd, _rn, reg_zero); \
1315- } \
1316-
1317-#define generate_op_and_imm(_rd, _rn) \
1318- generate_alu_immu(andi, and, _rd, _rn, imm) \
1319-
1320-#define generate_op_orr_imm(_rd, _rn) \
1321- generate_alu_immu(ori, or, _rd, _rn, imm) \
1322-
1323-#define generate_op_eor_imm(_rd, _rn) \
1324- generate_alu_immu(xori, xor, _rd, _rn, imm) \
1325-
1326-#define generate_op_bic_imm(_rd, _rn) \
1327- generate_alu_immu(andi, and, _rd, _rn, (~imm)) \
1328-
1329-#define generate_op_sub_imm(_rd, _rn) \
1330- generate_alu_imm(addiu, addu, _rd, _rn, (-imm)) \
1331-
1332-#define generate_op_rsb_imm(_rd, _rn) \
1333- if(imm != 0) \
1334- { \
1335- generate_load_imm(reg_temp, imm); \
1336- mips_emit_subu(_rd, reg_temp, _rn); \
1337- } \
1338- else \
1339- { \
1340- mips_emit_subu(_rd, reg_zero, _rn); \
1341- } \
1342-
1343-#define generate_op_sbc_imm(_rd, _rn) \
1344- generate_op_imm_wrapper(sbc, _rd, _rn) \
1345-
1346-#define generate_op_rsc_imm(_rd, _rn) \
1347- generate_op_imm_wrapper(rsc, _rd, _rn) \
1348-
1349-#define generate_op_add_imm(_rd, _rn) \
1350- generate_alu_imm(addiu, addu, _rd, _rn, imm) \
1351-
1352-#define generate_op_adc_imm(_rd, _rn) \
1353- generate_op_imm_wrapper(adc, _rd, _rn) \
1354-
1355-#define generate_op_mov_imm(_rd, _rn) \
1356- generate_load_imm(_rd, imm) \
1357-
1358-#define generate_op_mvn_imm(_rd, _rn) \
1359- generate_load_imm(_rd, (~imm)) \
1360-
1361-#define generate_op_logic_flags(_rd) \
1362- if(check_generate_n_flag) \
1363- { \
1364- mips_emit_srl(reg_n_cache, _rd, 31); \
1365- } \
1366- if(check_generate_z_flag) \
1367- { \
1368- mips_emit_sltiu(reg_z_cache, _rd, 1); \
1369- } \
1370-
1371-#define generate_op_sub_flags_prologue(_rn, _rm) \
1372- if(check_generate_c_flag) \
1373- { \
1374- mips_emit_sltu(reg_c_cache, _rn, _rm); \
1375- mips_emit_xori(reg_c_cache, reg_c_cache, 1); \
1376- } \
1377- if(check_generate_v_flag) \
1378- { \
1379- mips_emit_slt(reg_v_cache, _rn, _rm); \
1380- } \
1381-
1382-#define generate_op_sub_flags_epilogue(_rd) \
1383- generate_op_logic_flags(_rd); \
1384- if(check_generate_v_flag) \
1385- { \
1386- if(!check_generate_n_flag) \
1387- { \
1388- mips_emit_srl(reg_n_cache, _rd, 31); \
1389- } \
1390- mips_emit_xor(reg_v_cache, reg_v_cache, reg_n_cache); \
1391- } \
1392-
1393-#define generate_add_flags_prologue(_rn, _rm) \
1394- if(check_generate_c_flag | check_generate_v_flag) \
1395- { \
1396- mips_emit_addu(reg_c_cache, _rn, reg_zero); \
1397- } \
1398- if(check_generate_v_flag) \
1399- { \
1400- mips_emit_slt(reg_v_cache, _rm, reg_zero); \
1401- } \
1402-
1403-#define generate_add_flags_epilogue(_rd) \
1404- if(check_generate_v_flag) \
1405- { \
1406- mips_emit_slt(reg_a0, _rd, reg_c_cache); \
1407- mips_emit_xor(reg_v_cache, reg_v_cache, reg_a0); \
1408- } \
1409- if(check_generate_c_flag) \
1410- { \
1411- mips_emit_sltu(reg_c_cache, _rd, reg_c_cache); \
1412- } \
1413- generate_op_logic_flags(_rd) \
1414-
1415-#define generate_op_ands_reg(_rd, _rn, _rm) \
1416- mips_emit_and(_rd, _rn, _rm); \
1417- generate_op_logic_flags(_rd) \
1418-
1419-#define generate_op_orrs_reg(_rd, _rn, _rm) \
1420- mips_emit_or(_rd, _rn, _rm); \
1421- generate_op_logic_flags(_rd) \
1422-
1423-#define generate_op_eors_reg(_rd, _rn, _rm) \
1424- mips_emit_xor(_rd, _rn, _rm); \
1425- generate_op_logic_flags(_rd) \
1426-
1427-#define generate_op_bics_reg(_rd, _rn, _rm) \
1428- mips_emit_nor(reg_temp, _rm, reg_zero); \
1429- mips_emit_and(_rd, _rn, reg_temp); \
1430- generate_op_logic_flags(_rd) \
1431-
1432-#define generate_op_subs_reg(_rd, _rn, _rm) \
1433- generate_op_sub_flags_prologue(_rn, _rm); \
1434- mips_emit_subu(_rd, _rn, _rm); \
1435- generate_op_sub_flags_epilogue(_rd) \
1436-
1437-#define generate_op_rsbs_reg(_rd, _rn, _rm) \
1438- generate_op_sub_flags_prologue(_rm, _rn); \
1439- mips_emit_subu(_rd, _rm, _rn); \
1440- generate_op_sub_flags_epilogue(_rd) \
1441-
1442-/* SBCS Rd = Rn - <Oprnd> - NOT(Carry) */
1443-#define generate_op_sbcs_reg(_rd, _rn, _rm) \
1444- mips_emit_xori(reg_temp, reg_c_cache, 1); \
1445- mips_emit_addu(reg_temp, _rm, reg_temp); \
1446- generate_op_sub_flags_prologue(_rn, reg_temp); \
1447- mips_emit_subu(_rd, _rn, reg_temp); \
1448- generate_op_sub_flags_epilogue(_rd) \
1449-
1450-/* RSCS Rd = <Oprnd> - Rn - NOT(Carry) */
1451-#define generate_op_rscs_reg(_rd, _rn, _rm) \
1452- mips_emit_xori(reg_temp, reg_c_cache, 1); \
1453- mips_emit_addu(reg_temp, _rn, reg_temp); \
1454- generate_op_sub_flags_prologue(_rm, reg_temp); \
1455- mips_emit_subu(_rd, _rm, reg_temp); \
1456- generate_op_sub_flags_epilogue(_rd) \
1457-
1458-#define generate_op_adds_reg(_rd, _rn, _rm) \
1459- generate_add_flags_prologue(_rn, _rm); \
1460- mips_emit_addu(_rd, _rn, _rm); \
1461- generate_add_flags_epilogue(_rd) \
1462-
1463-#define generate_op_adcs_reg(_rd, _rn, _rm) \
1464- mips_emit_addu(reg_temp, _rm, reg_c_cache); \
1465- generate_add_flags_prologue(_rn, reg_temp); \
1466- mips_emit_addu(_rd, _rn, reg_temp); \
1467- generate_add_flags_epilogue(_rd) \
1468-
1469-#define generate_op_movs_reg(_rd, _rn, _rm) \
1470- mips_emit_addu(_rd, _rm, reg_zero); \
1471- generate_op_logic_flags(_rd) \
1472-
1473-#define generate_op_mvns_reg(_rd, _rn, _rm) \
1474- mips_emit_nor(_rd, _rm, reg_zero); \
1475- generate_op_logic_flags(_rd) \
1476-
1477-#define generate_op_neg_reg(_rd, _rn, _rm) \
1478- generate_op_subs_reg(_rd, reg_zero, _rm) \
1479-
1480-#define generate_op_muls_reg(_rd, _rn, _rm) \
1481- mips_emit_multu(_rn, _rm); \
1482- mips_emit_mflo(_rd); \
1483- generate_op_logic_flags(_rd) \
1484-
1485-#define generate_op_cmp_reg(_rd, _rn, _rm) \
1486- generate_op_subs_reg(reg_temp, _rn, _rm) \
1487-
1488-#define generate_op_cmn_reg(_rd, _rn, _rm) \
1489- generate_op_adds_reg(reg_temp, _rn, _rm) \
1490-
1491-#define generate_op_tst_reg(_rd, _rn, _rm) \
1492- generate_op_ands_reg(reg_temp, _rn, _rm) \
1493-
1494-#define generate_op_teq_reg(_rd, _rn, _rm) \
1495- generate_op_eors_reg(reg_temp, _rn, _rm) \
1496-
1497-#define generate_op_ands_imm(_rd, _rn) \
1498- generate_alu_immu(andi, and, _rd, _rn, imm); \
1499- generate_op_logic_flags(_rd) \
1500-
1501-#define generate_op_orrs_imm(_rd, _rn) \
1502- generate_alu_immu(ori, or, _rd, _rn, imm); \
1503- generate_op_logic_flags(_rd) \
1504-
1505-#define generate_op_eors_imm(_rd, _rn) \
1506- generate_alu_immu(xori, xor, _rd, _rn, imm); \
1507- generate_op_logic_flags(_rd) \
1508-
1509-#define generate_op_bics_imm(_rd, _rn) \
1510- generate_alu_immu(andi, and, _rd, _rn, (~imm)); \
1511- generate_op_logic_flags(_rd) \
1512-
1513-#define generate_op_subs_imm(_rd, _rn) \
1514- generate_op_imm_wrapper(subs, _rd, _rn) \
1515-
1516-#define generate_op_rsbs_imm(_rd, _rn) \
1517- generate_op_imm_wrapper(rsbs, _rd, _rn) \
1518-
1519-#define generate_op_sbcs_imm(_rd, _rn) \
1520- generate_op_imm_wrapper(sbcs, _rd, _rn) \
1521-
1522-#define generate_op_rscs_imm(_rd, _rn) \
1523- generate_op_imm_wrapper(rscs, _rd, _rn) \
1524-
1525-#define generate_op_adds_imm(_rd, _rn) \
1526- generate_op_imm_wrapper(adds, _rd, _rn) \
1527-
1528-#define generate_op_adcs_imm(_rd, _rn) \
1529- generate_op_imm_wrapper(adcs, _rd, _rn) \
1530-
1531-#define generate_op_movs_imm(_rd, _rn) \
1532- generate_load_imm(_rd, imm); \
1533- generate_op_logic_flags(_rd) \
1534-
1535-#define generate_op_mvns_imm(_rd, _rn) \
1536- generate_load_imm(_rd, (~imm)); \
1537- generate_op_logic_flags(_rd) \
1538-
1539-#define generate_op_cmp_imm(_rd, _rn) \
1540- generate_op_imm_wrapper(cmp, _rd, _rn) \
1541-
1542-#define generate_op_cmn_imm(_rd, _rn) \
1543- generate_op_imm_wrapper(cmn, _rd, _rn) \
1544-
1545-#define generate_op_tst_imm(_rd, _rn) \
1546- generate_op_ands_imm(reg_temp, _rn) \
1547-
1548-#define generate_op_teq_imm(_rd, _rn) \
1549- generate_op_eors_imm(reg_temp, _rn) \
1550-
1551-#define arm_generate_op_load_yes() \
1552- generate_load_reg_pc(reg_a1, rn, 8) \
1553-
1554-#define arm_generate_op_load_no() \
1555-
1556-#define arm_op_check_yes() \
1557- check_load_reg_pc(arm_reg_a1, rn, 8) \
1558-
1559-#define arm_op_check_no() \
1560-
1561-#define arm_generate_op_reg_flags(name, load_op) \
1562- arm_decode_data_proc_reg(); \
1563- if(check_generate_c_flag) \
1564- { \
1565- rm = generate_load_rm_sh_flags(rm); \
1566- } \
1567- else \
1568- { \
1569- rm = generate_load_rm_sh_no_flags(rm); \
1570- } \
1571- arm_op_check_##load_op(); \
1572- generate_op_##name##_reg(arm_to_mips_reg[rd], arm_to_mips_reg[rn], \
1573- arm_to_mips_reg[rm]) \
1574-
1575-#define arm_generate_op_reg(name, load_op) \
1576- arm_decode_data_proc_reg(); \
1577- rm = generate_load_rm_sh_no_flags(rm); \
1578- arm_op_check_##load_op(); \
1579- generate_op_##name##_reg(arm_to_mips_reg[rd], arm_to_mips_reg[rn], \
1580- arm_to_mips_reg[rm]) \
1581-
1582-#define arm_generate_op_imm(name, load_op) \
1583- arm_decode_data_proc_imm(); \
1584- arm_op_check_##load_op(); \
1585- generate_op_##name##_imm(arm_to_mips_reg[rd], arm_to_mips_reg[rn]) \
1586-
1587-#define arm_generate_op_imm_flags(name, load_op) \
1588- arm_generate_op_imm(name, load_op) \
1589-
1590-
1591-/* 1S+x+y */
1592-/* x=1I cycles if Op2 shifted-by-register. y=1S+1N cycles if Rd=R15. */
1593-#define cycle_arm_data_proc_reg() \
1594- if(rd == reg_pc) \
1595- { \
1596- cycle_count += 3 + cycle_arm_base(pc); \
1597- } \
1598- else \
1599- { \
1600- cycle_count += 1 + cycle_arm_fetch(pc); \
1601- } \
1602-
1603-#define cycle_arm_data_proc_reg_flags() \
1604- cycle_arm_data_proc_reg() \
1605-
1606-#define cycle_arm_data_proc_imm() \
1607- cycle_count += cycle_arm_base(pc); \
1608- if(rd == reg_pc) \
1609- { \
1610- cycle_count += 2; \
1611- } \
1612-
1613-#define cycle_arm_data_proc_imm_flags() \
1614- cycle_arm_data_proc_imm() \
1615-
1616-/* 1S+x */
1617-#define cycle_arm_data_proc_test_reg() \
1618- cycle_count += 1 + cycle_arm_fetch(pc) \
1619-
1620-#define cycle_arm_data_proc_test_reg_flags() \
1621- cycle_arm_data_proc_test_reg() \
1622-
1623-#define cycle_arm_data_proc_test_imm() \
1624- cycle_count += cycle_arm_base(pc) \
1625-
1626-#define cycle_arm_data_proc_test_imm_flags() \
1627- cycle_arm_data_proc_test_imm() \
1628-
1629-/* AND, EOR, SUB, RSB, ADD, ADC, SBC, RSC, ORR, BIC 1S+x+y */
1630-#define arm_data_proc(name, type, flags_op) \
1631-{ \
1632- arm_generate_op_##type(name, yes); \
1633- cycle_arm_data_proc_##type(); \
1634- check_store_reg_pc_##flags_op(rd); \
1635-} \
1636-
1637-/* TST, TEQ, CMP, CMN 1S+x */
1638-#define arm_data_proc_test(name, type) \
1639-{ \
1640- arm_generate_op_##type(name, yes); \
1641- cycle_arm_data_proc_test_##type(); \
1642-} \
1643-
1644-/* MOV, MVN 1S+x+y */
1645-#define arm_data_proc_unary(name, type, flags_op) \
1646-{ \
1647- arm_generate_op_##type(name, no); \
1648- cycle_arm_data_proc_##type(); \
1649- check_store_reg_pc_##flags_op(rd); \
1650-} \
1651-
1652-
1653-#define arm_multiply_flags_yes(_rd) \
1654- generate_op_logic_flags(_rd) \
1655-
1656-#define arm_multiply_flags_no(_rd) \
1657-
1658-#define arm_multiply_add_no() \
1659- mips_emit_mflo(arm_to_mips_reg[rd]) \
1660-
1661-#define arm_multiply_add_yes() \
1662- mips_emit_mflo(reg_temp); \
1663- mips_emit_addu(arm_to_mips_reg[rd], reg_temp, arm_to_mips_reg[rn]) \
1664-
1665-/* 1S+mI */
1666-#define cycle_arm_multiply_add_no() \
1667- cycle_count += cycle_arm_fetch(pc) + cycle_multiply(rs) \
1668-
1669-/* 1S+mI+1I */
1670-#define cycle_arm_multiply_add_yes() \
1671- cycle_count += 1 + cycle_arm_fetch(pc) + cycle_multiply(rs) \
1672-
1673-#define arm_multiply(add_op, flags) \
1674-{ \
1675- arm_decode_multiply(); \
1676- cycle_arm_multiply_add_##add_op(); \
1677- mips_emit_multu(arm_to_mips_reg[rm], arm_to_mips_reg[rs]); \
1678- arm_multiply_add_##add_op(); \
1679- arm_multiply_flags_##flags(arm_to_mips_reg[rd]); \
1680-} \
1681-
1682-#define arm_multiply_long_flags_yes(_rdlo, _rdhi) \
1683- mips_emit_sltiu(reg_z_cache, _rdlo, 1); \
1684- mips_emit_sltiu(reg_a0, _rdhi, 1); \
1685- mips_emit_and(reg_z_cache, reg_z_cache, reg_a0); \
1686- mips_emit_srl(reg_n_cache, _rdhi, 31); \
1687-
1688-#define arm_multiply_long_flags_no(_rdlo, _rdhi) \
1689-
1690-#define arm_multiply_long_add_yes(name) \
1691- mips_emit_mtlo(arm_to_mips_reg[rdlo]); \
1692- mips_emit_mthi(arm_to_mips_reg[rdhi]); \
1693- generate_multiply_##name() \
1694-
1695-#define arm_multiply_long_add_no(name) \
1696- generate_multiply_##name() \
1697-
1698-/* 1S+mI+1I */
1699-#define cycle_arm_multiply_long_add_no() \
1700- cycle_count += 1 + cycle_arm_fetch(pc) + cycle_multiply(rs) \
1701-
1702-/* 1S+mI+2I */
1703-#define cycle_arm_multiply_long_add_yes() \
1704- cycle_count += 2 + cycle_arm_fetch(pc) + cycle_multiply(rs) \
1705-
1706-#define arm_multiply_long(name, add_op, flags) \
1707-{ \
1708- arm_decode_multiply_long(); \
1709- cycle_arm_multiply_long_add_##add_op(); \
1710- arm_multiply_long_add_##add_op(name); \
1711- mips_emit_mflo(arm_to_mips_reg[rdlo]); \
1712- mips_emit_mfhi(arm_to_mips_reg[rdhi]); \
1713- arm_multiply_long_flags_##flags(arm_to_mips_reg[rdlo], \
1714- arm_to_mips_reg[rdhi]); \
1715-} \
1716-
1717-#define arm_psr_read(op_type, psr_reg) \
1718- generate_function_call(execute_read_##psr_reg); \
1719- generate_store_reg(reg_rv, rd) \
1720-
1721-u32 execute_store_cpsr_body(u32 _cpsr, u32 store_mask, u32 address)
1722-{
1723- reg[REG_CPSR] = _cpsr;
1724- if(store_mask & 0xFF)
1725- {
1726- set_cpu_mode(cpu_modes[_cpsr & 0x1F]);
1727-
1728- if((io_registers[REG_IE] & io_registers[REG_IF]) &&
1729- io_registers[REG_IME] && ((_cpsr & 0x80) == 0))
1730- {
1731- reg_mode[MODE_IRQ][6] = address + 4;
1732- spsr[MODE_IRQ] = _cpsr;
1733- reg[REG_CPSR] = (reg[REG_CPSR] & ~0xFF) | 0xD2;
1734- set_cpu_mode(MODE_IRQ);
1735-
1736- return 0x00000018;
1737- }
1738- }
1739-
1740- return 0;
1741-}
1742-
1743-#define arm_psr_load_new_reg() \
1744- generate_load_reg(reg_a0, rm) \
1745-
1746-#define arm_psr_load_new_imm() \
1747- generate_load_imm(reg_a0, imm) \
1748-
1749-#define arm_psr_store(op_type, psr_reg) \
1750- arm_psr_load_new_##op_type(); \
1751- generate_load_imm(reg_a1, psr_masks[psr_field]); \
1752- generate_load_pc(reg_a2, (pc + 4)); \
1753- generate_function_call_swap_delay(execute_store_##psr_reg) \
1754-
1755-#define arm_psr(op_type, transfer_type, psr_reg) \
1756-{ \
1757- arm_decode_psr_##op_type(); \
1758- cycle_count += cycle_arm_base(pc); \
1759- arm_psr_##transfer_type(op_type, psr_reg); \
1760-} \
1761-
1762-/* LDR: 1S+1N+1I. LDR PC: 2S+2N+1I. STR: 2N. */
1763-#define cycle_arm_access_memory_load_u32() \
1764- cycle_count += \
1765-/* 1 + cycle_arm_fetch(pc) + waitstate_cycles_non_seq[1][reg_a0 >> 24]; */ \
1766- cycle_arm_fetch(pc) + waitstate_cycles_non_seq[1][reg_a0 >> 24]; \
1767- if(rd == reg_pc) \
1768- { \
1769- cycle_count += 2; \
1770- } \
1771-
1772-#define cycle_arm_access_memory_load_u16() \
1773- cycle_count += \
1774-/* 1 + cycle_arm_fetch(pc) + waitstate_cycles_non_seq[0][reg_a0 >> 24]; */ \
1775- cycle_arm_fetch(pc) + waitstate_cycles_non_seq[0][reg_a0 >> 24]; \
1776- if(rd == reg_pc) \
1777- { \
1778- cycle_count += 2; \
1779- } \
1780-
1781-#define cycle_arm_access_memory_load_s16() \
1782- cycle_arm_access_memory_load_u16() \
1783-
1784-#define cycle_arm_access_memory_load_u8() \
1785- cycle_arm_access_memory_load_u16() \
1786-
1787-#define cycle_arm_access_memory_load_s8() \
1788- cycle_arm_access_memory_load_u16() \
1789-
1790-#define cycle_arm_access_memory_store_u32() \
1791- cycle_count += \
1792- cycle_arm_fetch(pc) + waitstate_cycles_non_seq[1][reg_a0 >> 24] \
1793-
1794-#define cycle_arm_access_memory_store_u16() \
1795- cycle_count += \
1796- cycle_arm_fetch(pc) + waitstate_cycles_non_seq[0][reg_a0 >> 24] \
1797-
1798-#define cycle_arm_access_memory_store_s16() \
1799- cycle_arm_access_memory_store_u16() \
1800-
1801-#define cycle_arm_access_memory_store_u8() \
1802- cycle_arm_access_memory_store_u16() \
1803-
1804-#define cycle_arm_access_memory_store_s8() \
1805- cycle_arm_access_memory_store_u16() \
1806-
1807-#define arm_access_memory_load(mem_type) \
1808- cycle_arm_access_memory_load_##mem_type(); \
1809- mips_emit_jal(mips_absolute_offset(execute_load_##mem_type)); \
1810- generate_load_pc(reg_a1, (pc + 8)); \
1811- generate_store_reg(reg_rv, rd); \
1812- check_store_reg_pc_no_flags(rd) \
1813-
1814-#define arm_access_memory_store(mem_type) \
1815- cycle_arm_access_memory_store_##mem_type(); \
1816- generate_load_pc(reg_a2, (pc + 4)); \
1817- generate_load_reg_pc(reg_a1, rd, 12); \
1818- generate_function_call_swap_delay(execute_store_##mem_type) \
1819-
1820-#define arm_access_memory_reg_pre_up() \
1821- mips_emit_addu(reg_a0, arm_to_mips_reg[rn], arm_to_mips_reg[rm]) \
1822-
1823-#define arm_access_memory_reg_pre_down() \
1824- mips_emit_subu(reg_a0, arm_to_mips_reg[rn], arm_to_mips_reg[rm]) \
1825-
1826-#define arm_access_memory_reg_pre(adjust_dir) \
1827- check_load_reg_pc(arm_reg_a0, rn, 8); \
1828- arm_access_memory_reg_pre_##adjust_dir() \
1829-
1830-#define arm_access_memory_reg_pre_wb(adjust_dir) \
1831- arm_access_memory_reg_pre(adjust_dir); \
1832- generate_store_reg(reg_a0, rn) \
1833-
1834-#define arm_access_memory_reg_post_up() \
1835- mips_emit_addu(arm_to_mips_reg[rn], arm_to_mips_reg[rn], \
1836- arm_to_mips_reg[rm]) \
1837-
1838-#define arm_access_memory_reg_post_down() \
1839- mips_emit_subu(arm_to_mips_reg[rn], arm_to_mips_reg[rn], \
1840- arm_to_mips_reg[rm]) \
1841-
1842-#define arm_access_memory_reg_post(adjust_dir) \
1843- generate_load_reg(reg_a0, rn); \
1844- arm_access_memory_reg_post_##adjust_dir() \
1845-
1846-#define arm_access_memory_imm_pre_up() \
1847- mips_emit_addiu(reg_a0, arm_to_mips_reg[rn], offset) \
1848-
1849-#define arm_access_memory_imm_pre_down() \
1850- mips_emit_addiu(reg_a0, arm_to_mips_reg[rn], -offset) \
1851-
1852-#define arm_access_memory_imm_pre(adjust_dir) \
1853- check_load_reg_pc(arm_reg_a0, rn, 8); \
1854- arm_access_memory_imm_pre_##adjust_dir() \
1855-
1856-#define arm_access_memory_imm_pre_wb(adjust_dir) \
1857- arm_access_memory_imm_pre(adjust_dir); \
1858- generate_store_reg(reg_a0, rn) \
1859-
1860-#define arm_access_memory_imm_post_up() \
1861- mips_emit_addiu(arm_to_mips_reg[rn], arm_to_mips_reg[rn], offset) \
1862-
1863-#define arm_access_memory_imm_post_down() \
1864- mips_emit_addiu(arm_to_mips_reg[rn], arm_to_mips_reg[rn], -offset) \
1865-
1866-#define arm_access_memory_imm_post(adjust_dir) \
1867- generate_load_reg(reg_a0, rn); \
1868- arm_access_memory_imm_post_##adjust_dir() \
1869-
1870-#define arm_data_trans_reg(adjust_op, adjust_dir) \
1871- arm_decode_data_trans_reg(); \
1872- rm = generate_load_offset_sh(rm); \
1873- arm_access_memory_reg_##adjust_op(adjust_dir) \
1874-
1875-#define arm_data_trans_imm(adjust_op, adjust_dir) \
1876- arm_decode_data_trans_imm(); \
1877- arm_access_memory_imm_##adjust_op(adjust_dir) \
1878-
1879-#define arm_data_trans_half_reg(adjust_op, adjust_dir) \
1880- arm_decode_half_trans_r(); \
1881- arm_access_memory_reg_##adjust_op(adjust_dir) \
1882-
1883-#define arm_data_trans_half_imm(adjust_op, adjust_dir) \
1884- arm_decode_half_trans_of(); \
1885- arm_access_memory_imm_##adjust_op(adjust_dir) \
1886-
1887-#define arm_access_memory(access_type, direction, adjust_op, mem_type, \
1888- offset_type) \
1889-{ \
1890- arm_data_trans_##offset_type(adjust_op, direction); \
1891- arm_access_memory_##access_type(mem_type); \
1892-} \
1893-
1894-#define word_bit_count(word) \
1895- (bit_count[word >> 8] + bit_count[word & 0xFF]) \
1896-
1897-#define sprint_no(access_type, pre_op, post_op, wb) \
1898-
1899-#define sprint_yes(access_type, pre_op, post_op, wb) \
1900- printf("sbit on %s %s %s %s\n", #access_type, #pre_op, #post_op, #wb) \
1901-
1902-/* LDM, nS+1N+1I. LDM PC, (n+1)S+2N+1I. STM (n-1)S+2N. */
1903-#define arm_block_memory_load() \
1904- block_memory_waitstate(reg_a0 >> 24); \
1905- generate_function_call_swap_delay(execute_aligned_load32); \
1906- generate_store_reg(reg_rv, i) \
1907-
1908-#define arm_block_memory_store() \
1909- block_memory_waitstate(reg_a0 >> 24); \
1910- generate_load_reg_pc(reg_a1, i, 8); \
1911- generate_function_call_swap_delay(execute_aligned_store32) \
1912-
1913-#define arm_block_memory_final_load() \
1914- arm_block_memory_load() \
1915-
1916-#define arm_block_memory_final_store() \
1917- generate_load_pc(reg_a2, (pc + 4)); \
1918- mips_emit_jal(mips_absolute_offset(execute_store_u32)); \
1919- generate_load_reg(reg_a1, i) \
1920-
1921-#define arm_block_memory_adjust_pc_store() \
1922-
1923-#define arm_block_memory_adjust_pc_load() \
1924- cycle_count++; \
1925- if(reg_list & 0x8000) \
1926- { \
1927- cycle_count += 2; \
1928- generate_mov(reg_a0, reg_rv); \
1929- generate_indirect_branch_arm(); \
1930- } \
1931-
1932-#define arm_block_memory_sp_load() \
1933- mips_emit_lw(arm_to_mips_reg[i], reg_a1, offset); \
1934-
1935-#define arm_block_memory_sp_store() \
1936-{ \
1937- u32 store_reg = i; \
1938- check_load_reg_pc(arm_reg_a0, store_reg, 8); \
1939- mips_emit_sw(arm_to_mips_reg[store_reg], reg_a1, offset); \
1940-} \
1941-
1942-#define arm_block_memory_sp_adjust_pc_store() \
1943-
1944-#define arm_block_memory_sp_adjust_pc_load() \
1945- cycle_count++; \
1946- if(reg_list & 0x8000) \
1947- { \
1948- cycle_count += 2; \
1949- generate_indirect_branch_arm(); \
1950- } \
1951-
1952-/* ポストデクリメント アドレッシング */
1953-#define arm_block_memory_offset_down_a() \
1954- mips_emit_addiu(reg_a2, base_reg, (-((word_bit_count(reg_list) - 1) << 2))) \
1955-
1956-/* プレデクリメント アドレッシング */
1957-#define arm_block_memory_offset_down_b() \
1958- mips_emit_addiu(reg_a2, base_reg, (-(word_bit_count(reg_list) << 2))) \
1959-
1960-/* ポストインクリメント アドレッシング */
1961-#define arm_block_memory_offset_no() \
1962- mips_emit_addu(reg_a2, base_reg, reg_zero) \
1963-
1964-/* プレインクリメント アドレッシング */
1965-#define arm_block_memory_offset_up() \
1966- mips_emit_addiu(reg_a2, base_reg, 4) \
1967-
1968-#define arm_block_memory_writeback_down() \
1969- mips_emit_addiu(base_reg, base_reg, (-(word_bit_count(reg_list) << 2))) \
1970-
1971-#define arm_block_memory_writeback_up() \
1972- mips_emit_addiu(base_reg, base_reg, (word_bit_count(reg_list) << 2)) \
1973-
1974-#define arm_block_memory_writeback_no()
1975-
1976-// Only emit writeback if the register is not in the list
1977-
1978-#define arm_block_memory_writeback_load(writeback_type) \
1979- if(!((reg_list >> rn) & 0x01)) \
1980- { \
1981- arm_block_memory_writeback_##writeback_type(); \
1982- } \
1983-
1984-#define arm_block_memory_writeback_store(writeback_type) \
1985- arm_block_memory_writeback_##writeback_type() \
1986-
1987-#define arm_block_memory(access_type, offset_type, writeback_type, s_bit) \
1988-{ \
1989- arm_decode_block_trans(); \
1990- u32 i; \
1991- u32 offset = 0; \
1992- u32 base_reg = arm_to_mips_reg[rn]; \
1993- \
1994- cycle_count += cycle_arm_fetch(pc); \
1995- \
1996- arm_block_memory_offset_##offset_type(); \
1997- arm_block_memory_writeback_##access_type(writeback_type); \
1998- \
1999- if((rn == REG_SP) && iwram_stack_optimize) \
2000- { \
2001- mips_emit_andi(reg_a1, reg_a2, 0x7FFC); \
2002- generate_load_imm(reg_a0, ((u32)(iwram + 0x8000))); \
2003- mips_emit_addu(reg_a1, reg_a1, reg_a0); \
2004- \
2005- for(i = 0; i < 16; i++) \
2006- { \
2007- if((reg_list >> i) & 0x01) \
2008- { \
2009- cycle_count++; \
2010- arm_block_memory_sp_##access_type(); \
2011- offset += 4; \
2012- } \
2013- } \
2014- arm_block_memory_sp_adjust_pc_##access_type(); \
2015- } \
2016- else \
2017- { \
2018- mips_emit_ins(reg_a2, reg_zero, 0, 2); \
2019- \
2020- for(i = 0; i < 16; i++) \
2021- { \
2022- if((reg_list >> i) & 0x01) \
2023- { \
2024- mips_emit_addiu(reg_a0, reg_a2, offset); \
2025- \
2026- if(reg_list & ~((2 << i) - 1)) \
2027- { \
2028- arm_block_memory_##access_type(); \
2029- offset += 4; \
2030- } \
2031- else \
2032- { \
2033- arm_block_memory_final_##access_type(); \
2034- break; \
2035- } \
2036- } \
2037- } \
2038- arm_block_memory_adjust_pc_##access_type(); \
2039- } \
2040-} \
2041-
2042-
2043-// This isn't really a correct implementation, may have to fix later.
2044-
2045-/* 1S+2N+1I */
2046-#define arm_swap(type) \
2047-{ \
2048- arm_decode_swap(); \
2049-/* cycle_count += 3 + cycle_arm_fetch(pc); */ \
2050- cycle_count += \
2051- 2 + cycle_arm_fetch(pc) + waitstate_cycles_non_seq[1][reg_a0 >> 24]; \
2052- mips_emit_jal(mips_absolute_offset(execute_load_##type)); \
2053- generate_load_reg(reg_a0, rn); \
2054- generate_mov(reg_a2, reg_rv); \
2055- generate_load_reg(reg_a0, rn); \
2056- cycle_count += waitstate_cycles_non_seq[1][reg_a0 >> 24]; \
2057- mips_emit_jal(mips_absolute_offset(execute_store_##type)); \
2058- generate_load_reg(reg_a1, rm); \
2059- generate_store_reg(reg_a2, rd); \
2060-} \
2061-
2062-
2063-#define thumb_generate_op_load_yes(_rs) \
2064- generate_load_reg(reg_a1, _rs) \
2065-
2066-#define thumb_generate_op_load_no(_rs) \
2067-
2068-#define thumb_generate_op_reg(name, _rd, _rs, _rn) \
2069- generate_op_##name##_reg(arm_to_mips_reg[_rd], \
2070- arm_to_mips_reg[_rs], arm_to_mips_reg[_rn]) \
2071-
2072-#define thumb_generate_op_imm(name, _rd, _rs, _rn) \
2073- generate_op_##name##_imm(arm_to_mips_reg[_rd], arm_to_mips_reg[_rs]) \
2074-
2075-// Types: add_sub, add_sub_imm, alu_op, imm
2076-// Affects N/Z/C/V flags
2077-
2078-#define thumb_data_proc(type, name, rn_type, _rd, _rs, _rn) \
2079-{ \
2080- thumb_decode_##type(); \
2081- cycle_count += cycle_thumb_base(pc); \
2082- thumb_generate_op_##rn_type(name, _rd, _rs, _rn); \
2083-} \
2084-
2085-/* 1S+mI */
2086-#define thumb_data_proc_muls(type, rn_type, _rd, _rs, _rn) \
2087-{ \
2088- thumb_decode_##type(); \
2089- cycle_count += cycle_thumb_fetch(pc) + cycle_multiply(_rs); \
2090- thumb_generate_op_##rn_type(muls, _rd, _rs, _rn); \
2091-} \
2092-
2093-#define thumb_data_proc_test(type, name, rn_type, _rs, _rn) \
2094-{ \
2095- thumb_decode_##type(); \
2096- cycle_count += cycle_thumb_base(pc); \
2097- thumb_generate_op_##rn_type(name, 0, _rs, _rn); \
2098-} \
2099-
2100-#define thumb_data_proc_unary(type, name, rn_type, _rd, _rn) \
2101-{ \
2102- thumb_decode_##type(); \
2103- cycle_count += cycle_thumb_base(pc); \
2104- thumb_generate_op_##rn_type(name, _rd, 0, _rn); \
2105-} \
2106-
2107-#define check_store_reg_pc_thumb(_rd) \
2108- if(_rd == REG_PC) \
2109- { \
2110- generate_indirect_branch_cycle_update(thumb); \
2111- } \
2112-
2113-#define thumb_data_proc_hi(name) \
2114-{ \
2115- thumb_decode_hireg_op(); \
2116- cycle_count += cycle_thumb_base(pc); \
2117- if(rd == reg_pc) \
2118- { \
2119- cycle_count += 2; \
2120- } \
2121- u32 dest_rd = rd; \
2122- check_load_reg_pc(arm_reg_a0, rs, 4); \
2123- check_load_reg_pc(arm_reg_a1, rd, 4); \
2124- generate_op_##name##_reg(arm_to_mips_reg[dest_rd], arm_to_mips_reg[rd], \
2125- arm_to_mips_reg[rs]); \
2126- check_store_reg_pc_thumb(dest_rd); \
2127-} \
2128-
2129-/*
2130-
2131-#define thumb_data_proc_hi(name) \
2132-{ \
2133- thumb_decode_hireg_op(); \
2134- check_load_reg_pc(arm_reg_a0, rs, 4); \
2135- check_load_reg_pc(arm_reg_a1, rd, 4); \
2136- generate_op_##name##_reg(arm_to_mips_reg[rd], arm_to_mips_reg[rd], \
2137- arm_to_mips_reg[rs]); \
2138- check_store_reg_pc_thumb(rd); \
2139-} \
2140-
2141-*/
2142-
2143-#define thumb_data_proc_test_hi(name) \
2144-{ \
2145- thumb_decode_hireg_op(); \
2146- cycle_count += cycle_thumb_base(pc); \
2147- check_load_reg_pc(arm_reg_a0, rs, 4); \
2148- check_load_reg_pc(arm_reg_a1, rd, 4); \
2149- generate_op_##name##_reg(reg_temp, arm_to_mips_reg[rd], \
2150- arm_to_mips_reg[rs]); \
2151-} \
2152-
2153-#define thumb_data_proc_mov_hi() \
2154-{ \
2155- thumb_decode_hireg_op(); \
2156- cycle_count += cycle_thumb_base(pc); \
2157- if(rd == reg_pc) \
2158- { \
2159- cycle_count += 2; \
2160- } \
2161- check_load_reg_pc(arm_reg_a0, rs, 4); \
2162- mips_emit_addu(arm_to_mips_reg[rd], arm_to_mips_reg[rs], reg_zero); \
2163- check_store_reg_pc_thumb(rd); \
2164-} \
2165-
2166-#define thumb_load_pc(_rd) \
2167-{ \
2168- thumb_decode_imm(); \
2169- cycle_count += cycle_thumb_base(pc); \
2170- generate_load_pc(arm_to_mips_reg[_rd], (((pc & ~2) + 4) + (imm << 2))); \
2171-} \
2172-
2173-#define thumb_load_sp(_rd) \
2174-{ \
2175- thumb_decode_imm(); \
2176- cycle_count += cycle_thumb_base(pc); \
2177- mips_emit_addiu(arm_to_mips_reg[_rd], reg_r13, (imm << 2)); \
2178-} \
2179-
2180-#define thumb_adjust_sp(value) \
2181-{ \
2182- thumb_decode_add_sp(); \
2183- cycle_count += cycle_thumb_base(pc); \
2184- mips_emit_addiu(reg_r13, reg_r13, (value)); \
2185-} \
2186-
2187-// Decode types: shift, alu_op
2188-// Operation types: lsl, lsr, asr, ror
2189-// Affects N/Z/C flags
2190-
2191-#define thumb_generate_shift_imm(name) \
2192- if(check_generate_c_flag) \
2193- { \
2194- generate_shift_imm_##name##_flags(rd, rs, imm); \
2195- } \
2196- else \
2197- { \
2198- generate_shift_imm_##name##_no_flags(rd, rs, imm); \
2199- } \
2200- if(rs != rd) \
2201- { \
2202- mips_emit_addu(arm_to_mips_reg[rd], arm_to_mips_reg[rs], reg_zero); \
2203- } \
2204-
2205-#define thumb_generate_shift_reg(name) \
2206-{ \
2207- u32 original_rd = rd; \
2208- if(check_generate_c_flag) \
2209- { \
2210- generate_shift_reg_##name##_flags(rd, rs); \
2211- } \
2212- else \
2213- { \
2214- generate_shift_reg_##name##_no_flags(rd, rs); \
2215- } \
2216- mips_emit_addu(arm_to_mips_reg[original_rd], reg_a0, reg_zero); \
2217-} \
2218-
2219-#define cycle_thumb_shift_shift() \
2220- cycle_count += cycle_thumb_base(pc) \
2221-
2222-/* ALU operations LSL,LSR,ASR,ROR 1S+1I */
2223-#define cycle_thumb_shift_alu_op() \
2224- cycle_count += 1 + cycle_thumb_fetch(pc) \
2225-
2226-#define thumb_shift(decode_type, op_type, value_type) \
2227-{ \
2228- cycle_thumb_shift_##decode_type(); \
2229- thumb_decode_##decode_type(); \
2230- thumb_generate_shift_##value_type(op_type); \
2231- generate_op_logic_flags(arm_to_mips_reg[rd]); \
2232-} \
2233-
2234-// Operation types: imm, mem_reg, mem_imm
2235-
2236-/* LDR 1S+1N+1I, STR 2N */
2237-#define cycle_thumb_access_memory_load_u32() \
2238- cycle_count += \
2239-/* 1 + cycle_thumb_fetch(pc) + waitstate_cycles_non_seq[1][reg_a0 >> 24] */ \
2240- cycle_thumb_fetch(pc) + waitstate_cycles_non_seq[1][reg_a0 >> 24] \
2241-
2242-#define cycle_thumb_access_memory_load_u16() \
2243- cycle_count += \
2244-/* 1 + cycle_thumb_fetch(pc) + waitstate_cycles_non_seq[0][reg_a0 >> 24] */ \
2245- cycle_thumb_fetch(pc) + waitstate_cycles_non_seq[0][reg_a0 >> 24] \
2246-
2247-#define cycle_thumb_access_memory_load_s16() \
2248- cycle_thumb_access_memory_load_u16() \
2249-
2250-#define cycle_thumb_access_memory_load_u8() \
2251- cycle_thumb_access_memory_load_u16() \
2252-
2253-#define cycle_thumb_access_memory_load_s8() \
2254- cycle_thumb_access_memory_load_u16() \
2255-
2256-#define cycle_thumb_access_memory_store_u32() \
2257- cycle_count += \
2258- cycle_thumb_fetch(pc) + waitstate_cycles_non_seq[1][reg_a0 >> 24] \
2259-
2260-#define cycle_thumb_access_memory_store_u16() \
2261- cycle_count += \
2262- cycle_thumb_fetch(pc) + waitstate_cycles_non_seq[0][reg_a0 >> 24] \
2263-
2264-#define cycle_thumb_access_memory_store_s16() \
2265- cycle_thumb_access_memory_store_u16() \
2266-
2267-#define cycle_thumb_access_memory_store_u8() \
2268- cycle_thumb_access_memory_store_u16() \
2269-
2270-#define cycle_thumb_access_memory_store_s8() \
2271- cycle_thumb_access_memory_store_u16() \
2272-
2273-#define thumb_access_memory_load(mem_type, reg_rd) \
2274- cycle_thumb_access_memory_load_##mem_type(); \
2275- mips_emit_jal(mips_absolute_offset(execute_load_##mem_type)); \
2276- generate_load_pc(reg_a1, (pc + 4)); \
2277- generate_store_reg(reg_rv, reg_rd) \
2278-
2279-#define thumb_access_memory_store(mem_type, reg_rd) \
2280- cycle_thumb_access_memory_store_##mem_type(); \
2281- generate_load_pc(reg_a2, (pc + 2)); \
2282- mips_emit_jal(mips_absolute_offset(execute_store_##mem_type)); \
2283- generate_load_reg(reg_a1, reg_rd) \
2284-
2285-#define thumb_access_memory_generate_address_pc_relative(offset, reg_rb, \
2286- reg_ro) \
2287- generate_load_pc(reg_a0, (offset)) \
2288-
2289-#define thumb_access_memory_generate_address_reg_imm(offset, reg_rb, reg_ro) \
2290- mips_emit_addiu(reg_a0, arm_to_mips_reg[reg_rb], (offset)) \
2291-
2292-#define thumb_access_memory_generate_address_reg_imm_sp(offset, reg_rb, reg_ro)\
2293- mips_emit_addiu(reg_a0, arm_to_mips_reg[reg_rb], (offset << 2)) \
2294-
2295-#define thumb_access_memory_generate_address_reg_reg(offset, reg_rb, reg_ro) \
2296- mips_emit_addu(reg_a0, arm_to_mips_reg[reg_rb], arm_to_mips_reg[reg_ro]) \
2297-
2298-#define thumb_access_memory(access_type, op_type, reg_rd, reg_rb, reg_ro, \
2299- address_type, offset, mem_type) \
2300-{ \
2301- thumb_decode_##op_type(); \
2302- thumb_access_memory_generate_address_##address_type(offset, reg_rb, reg_ro);\
2303- thumb_access_memory_##access_type(mem_type, reg_rd); \
2304-} \
2305-
2306-
2307-/* ポストインクリメント アドレッシング STMIA, LDMIA, POP */
2308-#define thumb_block_address_preadjust_no(base_reg) \
2309- mips_emit_addu(reg_a2, arm_to_mips_reg[base_reg], reg_zero) \
2310-
2311-/* プレデクリメント アドレッシング PUSH rlist */
2312-#define thumb_block_address_preadjust_down(base_reg) \
2313- mips_emit_addiu(reg_a2, arm_to_mips_reg[base_reg], \
2314- (-(bit_count[reg_list] << 2))); \
2315- mips_emit_addu(arm_to_mips_reg[base_reg], reg_a2, reg_zero) \
2316-
2317-/* プレデクリメント アドレッシング PUSH rlist, lr */
2318-#define thumb_block_address_preadjust_push_lr(base_reg) \
2319- mips_emit_addiu(reg_a2, arm_to_mips_reg[base_reg], \
2320- (-((bit_count[reg_list] + 1) << 2))); \
2321- mips_emit_addu(arm_to_mips_reg[base_reg], reg_a2, reg_zero) \
2322-
2323-/* ベースレジスタ更新 */
2324-#define thumb_block_address_postadjust_no(base_reg) \
2325-
2326-#define thumb_block_address_postadjust_up(base_reg) \
2327- mips_emit_addiu(arm_to_mips_reg[base_reg], reg_a2, \
2328- (bit_count[reg_list] << 2)) \
2329-
2330-#define thumb_block_address_postadjust_down(base_reg) \
2331- mips_emit_addiu(arm_to_mips_reg[base_reg], reg_a2, \
2332- (-(bit_count[reg_list] << 2))) \
2333-
2334-#define thumb_block_address_postadjust_pop_pc(base_reg) \
2335- mips_emit_addiu(arm_to_mips_reg[base_reg], reg_a2, \
2336- ((bit_count[reg_list] + 1) << 2)) \
2337-
2338-#define thumb_block_address_postadjust_push_lr(base_reg) \
2339-
2340-/* nS+1N+1I for LDM, (n-1)S+2N for STM */
2341-/* nS+1N+1I (POP), (n+1)S+2N+1I (POP PC), (n-1)S+2N (PUSH) */
2342-#define thumb_block_memory_load() \
2343- block_memory_waitstate(reg_a0 >> 24); \
2344- generate_function_call_swap_delay(execute_aligned_load32); \
2345- generate_store_reg(reg_rv, i) \
2346-
2347-#define thumb_block_memory_store() \
2348- block_memory_waitstate(reg_a0 >> 24); \
2349- mips_emit_jal(mips_absolute_offset(execute_aligned_store32)); \
2350- generate_load_reg(reg_a1, i) \
2351-
2352-#define thumb_block_memory_final_load() \
2353- cycle_count++; \
2354- thumb_block_memory_load() \
2355-
2356-#define thumb_block_memory_final_store() \
2357- generate_load_pc(reg_a2, (pc + 2)); \
2358- mips_emit_jal(mips_absolute_offset(execute_store_u32)); \
2359- generate_load_reg(reg_a1, i) \
2360-
2361-#define thumb_block_memory_final_no(access_type) \
2362- thumb_block_memory_final_##access_type() \
2363-
2364-#define thumb_block_memory_final_up(access_type) \
2365- thumb_block_memory_final_##access_type() \
2366-
2367-#define thumb_block_memory_final_down(access_type) \
2368- thumb_block_memory_final_##access_type() \
2369-
2370-#define thumb_block_memory_final_push_lr(access_type) \
2371- thumb_block_memory_##access_type() \
2372-
2373-#define thumb_block_memory_final_pop_pc(access_type) \
2374- thumb_block_memory_##access_type() \
2375-
2376-#define thumb_block_memory_extra_no() \
2377-
2378-#define thumb_block_memory_extra_up() \
2379-
2380-#define thumb_block_memory_extra_down() \
2381-
2382-#define thumb_block_memory_extra_push_lr() \
2383- mips_emit_addiu(reg_a0, reg_a2, (bit_count[reg_list] << 2)); \
2384- mips_emit_jal(mips_absolute_offset(execute_aligned_store32)); \
2385- generate_load_reg(reg_a1, REG_LR) \
2386-
2387-#define thumb_block_memory_extra_pop_pc() \
2388- cycle_count += 2; \
2389- mips_emit_jal(mips_absolute_offset(execute_aligned_load32)); \
2390- mips_emit_addiu(reg_a0, reg_a2, (bit_count[reg_list] << 2)); \
2391- generate_mov(reg_a0, reg_rv); \
2392- generate_indirect_branch_cycle_update(thumb) \
2393-
2394-#define thumb_block_memory_sp_load() \
2395- mips_emit_lw(arm_to_mips_reg[i], reg_a1, offset) \
2396-
2397-#define cycle_thumb_block_memory_sp_store() \
2398-
2399-#define cycle_thumb_block_memory_sp_load() \
2400- cycle_count++ \
2401-
2402-#define thumb_block_memory_sp_store() \
2403- mips_emit_sw(arm_to_mips_reg[i], reg_a1, offset) \
2404-
2405-#define thumb_block_memory_sp_extra_no() \
2406-
2407-#define thumb_block_memory_sp_extra_up() \
2408-
2409-/* PUSH rlist */
2410-#define thumb_block_memory_sp_extra_down() \
2411-
2412-/* POP PC */
2413-#define thumb_block_memory_sp_extra_pop_pc() \
2414- cycle_count += 2; \
2415- mips_emit_lw(reg_a0, reg_a1, (bit_count[reg_list] << 2)); \
2416- generate_indirect_branch_cycle_update(thumb) \
2417-
2418-/* PUSH LR */
2419-#define thumb_block_memory_sp_extra_push_lr() \
2420- mips_emit_sw(reg_r14, reg_a1, (bit_count[reg_list] << 2)) \
2421-
2422-#define thumb_block_memory_writeback_load(post_op, base_reg) \
2423- if(~((reg_list >> base_reg) & 0x01)) \
2424- { \
2425- thumb_block_address_postadjust_##post_op(base_reg); \
2426- } \
2427-
2428-#define thumb_block_memory_writeback_store(post_op, base_reg) \
2429- thumb_block_address_postadjust_##post_op(base_reg) \
2430-
2431-#define thumb_block_memory(access_type, pre_op, post_op, base_reg) \
2432-{ \
2433- thumb_decode_rlist(); \
2434- u32 i; \
2435- u32 offset = 0; \
2436- \
2437- cycle_count += cycle_thumb_fetch(pc); \
2438- \
2439- thumb_block_address_preadjust_##pre_op(base_reg); \
2440-/* thumb_block_address_postadjust_##post_op(base_reg); */ \
2441- thumb_block_memory_writeback_##access_type(post_op, base_reg); \
2442- \
2443- if((base_reg == REG_SP) && iwram_stack_optimize) \
2444- { \
2445- mips_emit_andi(reg_a1, reg_a2, 0x7FFC); \
2446- generate_load_imm(reg_a0, ((u32)(iwram + 0x8000))); \
2447- generate_add(reg_a1, reg_a0); \
2448- \
2449- for(i = 0; i < 8; i++) \
2450- { \
2451- if((reg_list >> i) & 0x01) \
2452- { \
2453- cycle_count++; \
2454- thumb_block_memory_sp_##access_type(); \
2455- offset += 4; \
2456- } \
2457- } \
2458- cycle_thumb_block_memory_sp_##access_type(); \
2459- thumb_block_memory_sp_extra_##post_op(); \
2460- } \
2461- else \
2462- { \
2463- mips_emit_ins(reg_a2, reg_zero, 0, 2); \
2464- \
2465- for(i = 0; i < 8; i++) \
2466- { \
2467- if((reg_list >> i) & 0x01) \
2468- { \
2469- mips_emit_addiu(reg_a0, reg_a2, offset); \
2470- \
2471- if(reg_list & ~((2 << i) - 1)) \
2472- { \
2473- thumb_block_memory_##access_type(); \
2474- offset += 4; \
2475- } \
2476- else \
2477- { \
2478- thumb_block_memory_final_##post_op(access_type); \
2479- break; \
2480- } \
2481- } \
2482- } \
2483- thumb_block_memory_extra_##post_op(); \
2484- } \
2485-} \
2486-
2487-
2488-#define thumb_conditional_branch(condition) \
2489-{ \
2490- cycle_count += 2 + cycle_thumb_fetch(pc); \
2491- CONDITION_CHECK_TYPE condition_check; \
2492- generate_condition_##condition(); \
2493- generate_branch_no_cycle_update( \
2494- block_exits[block_exit_position].branch_source, \
2495- block_exits[block_exit_position].branch_target); \
2496- generate_branch_patch_conditional(backpatch_address, translation_ptr); \
2497- block_exit_position++; \
2498-} \
2499-
2500-#define arm_conditional_block_header() \
2501- generate_condition() \
2502-
2503-#define arm_b() \
2504- cycle_count += 2 + cycle_arm_base(pc); \
2505- generate_branch() \
2506-
2507-#define arm_bl() \
2508- cycle_count += 2 + cycle_arm_base(pc); \
2509- generate_load_pc(reg_r14, (pc + 4)); \
2510- generate_branch() \
2511-
2512-#define arm_bx() \
2513- cycle_count += 2 + cycle_arm_base(pc); \
2514- arm_decode_branchx(); \
2515- generate_load_reg(reg_a0, rn); \
2516- /*generate_load_pc(reg_a2, pc);*/ \
2517- generate_indirect_branch_dual() \
2518-
2519-#define arm_swi() \
2520-{ \
2521- cycle_count += 2 + cycle_arm_base(pc); \
2522- generate_swi_hle_handler((opcode >> 16) & 0xFF); \
2523- generate_load_pc(reg_a0, (pc + 4)); \
2524- generate_function_call_swap_delay(execute_swi); \
2525- generate_branch(); \
2526-} \
2527-
2528-#define thumb_b() \
2529- cycle_count += 2 + cycle_thumb_base(pc); \
2530- generate_branch_cycle_update( \
2531- block_exits[block_exit_position].branch_source, \
2532- block_exits[block_exit_position].branch_target); \
2533- block_exit_position++ \
2534-
2535-#define thumb_bl() \
2536- cycle_count += 2 + cycle_thumb_base(pc); \
2537- generate_load_pc(reg_r14, ((pc + 2) | 0x01)); \
2538- generate_branch_cycle_update( \
2539- block_exits[block_exit_position].branch_source, \
2540- block_exits[block_exit_position].branch_target); \
2541- block_exit_position++ \
2542-
2543-#define thumb_blh() \
2544-{ \
2545- cycle_count += 2 + cycle_thumb_base(pc); \
2546- thumb_decode_branch(); \
2547- generate_alu_imm(addiu, addu, reg_a0, reg_r14, (offset << 1)); \
2548- generate_load_pc(reg_r14, ((pc + 2) | 0x01)); \
2549- generate_indirect_branch_cycle_update(thumb); \
2550-} \
2551-
2552-#define thumb_bx() \
2553-{ \
2554- cycle_count += 2 + cycle_thumb_base(pc); \
2555- thumb_decode_hireg_op(); \
2556- generate_load_reg_pc(reg_a0, rs, 4); \
2557- /*generate_load_pc(reg_a2, pc);*/ \
2558- generate_indirect_branch_cycle_update(dual); \
2559-} \
2560-
2561-#define thumb_swi() \
2562-{ \
2563- cycle_count += 2 + cycle_thumb_base(pc); \
2564- generate_swi_hle_handler(opcode & 0xFF); \
2565- generate_load_pc(reg_a0, (pc + 2)); \
2566- generate_function_call_swap_delay(execute_swi); \
2567- generate_branch_cycle_update( \
2568- block_exits[block_exit_position].branch_source, \
2569- block_exits[block_exit_position].branch_target); \
2570- block_exit_position++; \
2571-} \
2572-
2573-u8 swi_hle_handle[256] =
2574-{
2575- 0x0, // SWI 0: SoftReset
2576- 0x0, // SWI 1: RegisterRAMReset
2577- 0x0, // SWI 2: Halt
2578- 0x0, // SWI 3: Stop/Sleep
2579- 0x0, // SWI 4: IntrWait
2580- 0x0, // SWI 5: VBlankIntrWait
2581- 0x1, // SWI 6: Div
2582- 0x0, // SWI 7: DivArm
2583- 0x0, // SWI 8: Sqrt
2584- 0x0, // SWI 9: ArcTan
2585- 0x0, // SWI A: ArcTan2
2586- 0x0, // SWI B: CpuSet
2587- 0x0, // SWI C: CpuFastSet
2588- 0x1, // SWI D: GetBIOSCheckSum
2589- 0x0, // SWI E: BgAffineSet
2590- 0x0, // SWI F: ObjAffineSet
2591- 0x0, // SWI 10: BitUnpack
2592- 0x0, // SWI 11: LZ77UnCompWram
2593- 0x0, // SWI 12: LZ77UnCompVram
2594- 0x0, // SWI 13: HuffUnComp
2595- 0x0, // SWI 14: RLUnCompWram
2596- 0x0, // SWI 15: RLUnCompVram
2597- 0x0, // SWI 16: Diff8bitUnFilterWram
2598- 0x0, // SWI 17: Diff8bitUnFilterVram
2599- 0x0, // SWI 18: Diff16bitUnFilter
2600- 0x0, // SWI 19: SoundBias
2601- 0x0, // SWI 1A: SoundDriverInit
2602- 0x0, // SWI 1B: SoundDriverMode
2603- 0x0, // SWI 1C: SoundDriverMain
2604- 0x0, // SWI 1D: SoundDriverVSync
2605- 0x0, // SWI 1E: SoundChannelClear
2606- 0x0, // SWI 1F: MidiKey2Freq
2607- 0x0, // SWI 20: SoundWhatever0
2608- 0x0, // SWI 21: SoundWhatever1
2609- 0x0, // SWI 22: SoundWhatever2
2610- 0x0, // SWI 23: SoundWhatever3
2611- 0x0, // SWI 24: SoundWhatever4
2612- 0x0, // SWI 25: MultiBoot
2613- 0x0, // SWI 26: HardReset
2614- 0x0, // SWI 27: CustomHalt
2615- 0x0, // SWI 28: SoundDriverVSyncOff
2616- 0x0, // SWI 29: SoundDriverVSyncOn
2617- 0x0 // SWI 2A: SoundGetJumpList
2618-};
2619-
2620-#define generate_swi_hle_handler(_swi_number) \
2621-{ \
2622- u32 swi_number = _swi_number; \
2623- \
2624- if(swi_hle_handle[swi_number]) \
2625- { \
2626- /* Div */ \
2627- if(swi_number == 0x06) \
2628- { \
2629- mips_emit_div(reg_r0, reg_r1); \
2630- mips_emit_mflo(reg_r0); \
2631- mips_emit_mfhi(reg_r1); \
2632- mips_emit_sra(reg_a0, reg_r0, 31); \
2633- mips_emit_xor(reg_r3, reg_r0, reg_a0); \
2634- mips_emit_subu(reg_r3, reg_r3, reg_a0); \
2635- } \
2636- \
2637- /* GetBIOSCheckSum */ \
2638- if(swi_number == 0x0D) \
2639- { \
2640- generate_load_imm(reg_r0, 0xBAAE187F); \
2641- } \
2642- \
2643- break; \
2644- } \
2645-} \
2646-
2647-#define generate_translation_gate(type) \
2648- generate_load_pc(reg_a0, pc); \
2649- generate_indirect_branch_no_cycle_update(type) \
2650-
2651-#define generate_update_pc_reg() \
2652- generate_load_pc(reg_a0, pc); \
2653- mips_emit_sw(reg_a0, reg_base, (REG_PC << 2)) \
2654-
2655-
2656-#define cycle_arm_base(_address) \
2657- waitstate_cycles_seq[1][_address >> 24] \
2658-
2659-#define cycle_thumb_base(_address) \
2660- waitstate_cycles_seq[0][_address >> 24] \
2661-
2662-#define cycle_arm_fetch(_address) \
2663- waitstate_cycles_fetch[1][_address >> 24] \
2664-
2665-#define cycle_thumb_fetch(_address) \
2666- waitstate_cycles_fetch[0][_address >> 24] \
2667-
2668-#define block_memory_waitstate(mem_region) \
2669- if(offset == 0 || \
2670- (mem_region >= 0x08 && mem_region <= 0x0D && (reg_a0 % 0x20000) == 0)) \
2671- { \
2672- cycle_count += waitstate_cycles_non_seq[1][mem_region]; \
2673- } \
2674- else \
2675- { \
2676- cycle_count += waitstate_cycles_seq[1][mem_region]; \
2677- } \
2678-
2679-static u8 cycle_multiply(u32 _rs)
2680-{
2681- u32 mult_rs = arm_to_mips_reg[_rs];
2682-
2683- if(((s32)mult_rs) < 0)
2684- mult_rs = ~mult_rs;
2685-
2686- /* m=1 for Bit 31-8 */
2687- if((mult_rs & 0xFFFFFF00) == 0)
2688- return 1;
2689- else
2690- /* m=2 for Bit 31-16 */
2691- if((mult_rs & 0xFFFF0000) == 0)
2692- return 2;
2693- else
2694- /* m=3 for Bit 31-24 */
2695- if((mult_rs & 0xFF000000) == 0)
2696- return 3;
2697- else
2698- /* m=4 otherwise */
2699- return 4;
2700-}
2701-
2702-#endif /* MIPS_EMIT_H */
Deleted: svn:mime-type
## -1 +0,0 ##
-text/plain
\ No newline at end of property
--- trunk/gpsp-kai-test/src/mips_emit_new_count.h (revision 404)
+++ trunk/gpsp-kai-test/src/mips_emit_new_count.h (nonexistent)
@@ -1,2627 +0,0 @@
1-/* unofficial gameplaySP kai
2- *
3- * Copyright (C) 2006 Exophase <exophase@gmail.com>
4- * Copyright (C) 2007 takka <takka@tfact.net>
5- * Copyright (C) 2007 ????? <?????>
6- *
7- * This program is free software; you can redistribute it and/or
8- * modify it under the terms of the GNU General Public License as
9- * published by the Free Software Foundation; either version 2 of
10- * the License, or (at your option) any later version.
11- *
12- * This program is distributed in the hope that it will be useful,
13- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15- * General Public License for more details.
16- *
17- * You should have received a copy of the GNU General Public License
18- * along with this program; if not, write to the Free Software
19- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20- */
21-
22-#ifndef MIPS_EMIT_H
23-#define MIPS_EMIT_H
24-
25-u32 mips_update_gba(u32 pc);
26-
27-// Although these are defined as a function, don't call them as
28-// such (jump to it instead)
29-void mips_indirect_branch_arm(u32 address);
30-void mips_indirect_branch_thumb(u32 address);
31-void mips_indirect_branch_dual(u32 address);
32-
33-u32 execute_read_cpsr();
34-u32 execute_read_spsr();
35-void execute_swi(u32 pc);
36-
37-u32 execute_spsr_restore(u32 address);
38-void execute_store_cpsr(u32 new_cpsr, u32 store_mask);
39-void execute_store_spsr(u32 new_spsr, u32 store_mask);
40-
41-u32 execute_spsr_restore_body(u32 address);
42-u32 execute_store_cpsr_body(u32 _cpsr, u32 store_mask, u32 address);
43-
44-u32 execute_lsl_flags_reg(u32 value, u32 shift);
45-u32 execute_lsr_flags_reg(u32 value, u32 shift);
46-u32 execute_asr_flags_reg(u32 value, u32 shift);
47-u32 execute_ror_flags_reg(u32 value, u32 shift);
48-
49-void execute_aligned_store32(u32 address, u32 value);
50-u32 execute_aligned_load32(u32 address);
51-
52-void reg_check();
53-
54-typedef enum
55-{
56- mips_reg_zero, // 0
57- mips_reg_at, // 1
58- mips_reg_v0, // 2
59- mips_reg_v1, // 3
60- mips_reg_a0, // 4
61- mips_reg_a1, // 5
62- mips_reg_a2, // 6
63- mips_reg_a3, // 7
64- mips_reg_t0, // 8
65- mips_reg_t1, // 9
66- mips_reg_t2, // 10
67- mips_reg_t3, // 11
68- mips_reg_t4, // 12
69- mips_reg_t5, // 13
70- mips_reg_t6, // 14
71- mips_reg_t7, // 15
72- mips_reg_s0, // 16
73- mips_reg_s1, // 17
74- mips_reg_s2, // 18
75- mips_reg_s3, // 19
76- mips_reg_s4, // 20
77- mips_reg_s5, // 21
78- mips_reg_s6, // 22
79- mips_reg_s7, // 23
80- mips_reg_t8, // 24
81- mips_reg_t9, // 25
82- mips_reg_k0, // 26
83- mips_reg_k1, // 27
84- mips_reg_gp, // 28
85- mips_reg_sp, // 29
86- mips_reg_fp, // 30
87- mips_reg_ra // 31
88-} mips_reg_number;
89-
90-typedef enum
91-{
92- mips_special_sll = 0x00,
93- mips_special_srl = 0x02,
94- mips_special_sra = 0x03,
95- mips_special_sllv = 0x04,
96- mips_special_srlv = 0x06,
97- mips_special_srav = 0x07,
98- mips_special_jr = 0x08,
99- mips_special_jalr = 0x09,
100- mips_special_movz = 0x0A,
101- mips_special_movn = 0x0B,
102- mips_special_mfhi = 0x10,
103- mips_special_mthi = 0x11,
104- mips_special_mflo = 0x12,
105- mips_special_mtlo = 0x13,
106- mips_special_mult = 0x18,
107- mips_special_multu = 0x19,
108- mips_special_div = 0x1A,
109- mips_special_divu = 0x1B,
110- mips_special_madd = 0x1C,
111- mips_special_maddu = 0x1D,
112- mips_special_add = 0x20,
113- mips_special_addu = 0x21,
114- mips_special_sub = 0x22,
115- mips_special_subu = 0x23,
116- mips_special_and = 0x24,
117- mips_special_or = 0x25,
118- mips_special_xor = 0x26,
119- mips_special_nor = 0x27,
120- mips_special_slt = 0x2A,
121- mips_special_sltu = 0x2B
122-} mips_function_special;
123-
124-typedef enum
125-{
126- mips_special3_ext = 0x00,
127- mips_special3_ins = 0x04,
128- mips_special3_bshfl = 0x20
129-} mips_function_special3;
130-
131-typedef enum
132-{
133- mips_regimm_bltz = 0x00,
134- mips_regimm_bltzal = 0x10
135-} mips_function_regimm;
136-
137-typedef enum
138-{
139- mips_opcode_special = 0x00,
140- mips_opcode_regimm = 0x01,
141- mips_opcode_j = 0x02,
142- mips_opcode_jal = 0x03,
143- mips_opcode_beq = 0x04,
144- mips_opcode_bne = 0x05,
145- mips_opcode_blez = 0x06,
146- mips_opcode_bgtz = 0x07,
147- mips_opcode_addi = 0x08,
148- mips_opcode_addiu = 0x09,
149- mips_opcode_slti = 0x0A,
150- mips_opcode_sltiu = 0x0B,
151- mips_opcode_andi = 0x0C,
152- mips_opcode_ori = 0x0D,
153- mips_opcode_xori = 0x0E,
154- mips_opcode_lui = 0x0F,
155- mips_opcode_llo = 0x18,
156- mips_opcode_lhi = 0x19,
157- mips_opcode_trap = 0x1A,
158- mips_opcode_special2 = 0x1C,
159- mips_opcode_special3 = 0x1F,
160- mips_opcode_lb = 0x20,
161- mips_opcode_lh = 0x21,
162- mips_opcode_lw = 0x23,
163- mips_opcode_lbu = 0x24,
164- mips_opcode_lhu = 0x25,
165- mips_opcode_sb = 0x28,
166- mips_opcode_sh = 0x29,
167- mips_opcode_sw = 0x2B,
168-} mips_opcode;
169-
170-#define mips_emit_reg(opcode, rs, rt, rd, shift, function) \
171- *((u32 *)translation_ptr) = (mips_opcode_##opcode << 26) | \
172- (rs << 21) | (rt << 16) | (rd << 11) | (shift << 6) | function; \
173- translation_ptr += 4 \
174-
175-#define mips_emit_special(function, rs, rt, rd, shift) \
176- *((u32 *)translation_ptr) = (mips_opcode_special << 26) | \
177- (rs << 21) | (rt << 16) | (rd << 11) | (shift << 6) | \
178- mips_special_##function; \
179- translation_ptr += 4 \
180-
181-#define mips_emit_special3(function, rs, rt, imm_a, imm_b) \
182- *((u32 *)translation_ptr) = (mips_opcode_special3 << 26) | \
183- (rs << 21) | (rt << 16) | (imm_a << 11) | (imm_b << 6) | \
184- mips_special3_##function; \
185- translation_ptr += 4 \
186-
187-#define mips_emit_imm(opcode, rs, rt, immediate) \
188- *((u32 *)translation_ptr) = (mips_opcode_##opcode << 26) | \
189- (rs << 21) | (rt << 16) | (immediate & 0xFFFF); \
190- translation_ptr += 4 \
191-
192-#define mips_emit_regimm(function, rs, immediate) \
193- *((u32 *)translation_ptr) = (mips_opcode_regimm << 26) | \
194- (rs << 21) | (mips_regimm_##function << 16) | (immediate & 0xFFFF); \
195- translation_ptr += 4 \
196-
197-#define mips_emit_jump(opcode, offset) \
198- *((u32 *)translation_ptr) = (mips_opcode_##opcode << 26) | \
199- (offset & 0x3FFFFFF); \
200- translation_ptr += 4 \
201-
202-#define mips_relative_offset(source, offset) \
203- (((u32)offset - ((u32)source + 4)) / 4) \
204-
205-#define mips_absolute_offset(offset) \
206- ((u32)offset / 4) \
207-
208-// ADDU rd, rs, rt
209-#define mips_emit_addu(rd, rs, rt) \
210- mips_emit_special(addu, rs, rt, rd, 0) \
211-
212-#define mips_emit_subu(rd, rs, rt) \
213- mips_emit_special(subu, rs, rt, rd, 0) \
214-
215-#define mips_emit_xor(rd, rs, rt) \
216- mips_emit_special(xor, rs, rt, rd, 0) \
217-
218-#define mips_emit_add(rd, rs, rt) \
219- mips_emit_special(add, rs, rt, rd, 0) \
220-
221-#define mips_emit_sub(rd, rs, rt) \
222- mips_emit_special(sub, rs, rt, rd, 0) \
223-
224-#define mips_emit_and(rd, rs, rt) \
225- mips_emit_special(and, rs, rt, rd, 0) \
226-
227-#define mips_emit_or(rd, rs, rt) \
228- mips_emit_special(or, rs, rt, rd, 0) \
229-
230-#define mips_emit_nor(rd, rs, rt) \
231- mips_emit_special(nor, rs, rt, rd, 0) \
232-
233-#define mips_emit_slt(rd, rs, rt) \
234- mips_emit_special(slt, rs, rt, rd, 0) \
235-
236-#define mips_emit_sltu(rd, rs, rt) \
237- mips_emit_special(sltu, rs, rt, rd, 0) \
238-
239-#define mips_emit_sllv(rd, rt, rs) \
240- mips_emit_special(sllv, rs, rt, rd, 0) \
241-
242-#define mips_emit_srlv(rd, rt, rs) \
243- mips_emit_special(srlv, rs, rt, rd, 0) \
244-
245-#define mips_emit_srav(rd, rt, rs) \
246- mips_emit_special(srav, rs, rt, rd, 0) \
247-
248-#define mips_emit_rotrv(rd, rt, rs) \
249- mips_emit_special(srlv, rs, rt, rd, 1) \
250-
251-#define mips_emit_sll(rd, rt, shift) \
252- mips_emit_special(sll, 0, rt, rd, shift) \
253-
254-#define mips_emit_srl(rd, rt, shift) \
255- mips_emit_special(srl, 0, rt, rd, shift) \
256-
257-#define mips_emit_sra(rd, rt, shift) \
258- mips_emit_special(sra, 0, rt, rd, shift) \
259-
260-#define mips_emit_rotr(rd, rt, shift) \
261- mips_emit_special(srl, 1, rt, rd, shift) \
262-
263-#define mips_emit_mfhi(rd) \
264- mips_emit_special(mfhi, 0, 0, rd, 0) \
265-
266-#define mips_emit_mflo(rd) \
267- mips_emit_special(mflo, 0, 0, rd, 0) \
268-
269-#define mips_emit_mthi(rs) \
270- mips_emit_special(mthi, rs, 0, 0, 0) \
271-
272-#define mips_emit_mtlo(rs) \
273- mips_emit_special(mtlo, rs, 0, 0, 0) \
274-
275-#define mips_emit_mult(rs, rt) \
276- mips_emit_special(mult, rs, rt, 0, 0) \
277-
278-#define mips_emit_multu(rs, rt) \
279- mips_emit_special(multu, rs, rt, 0, 0) \
280-
281-#define mips_emit_div(rs, rt) \
282- mips_emit_special(div, rs, rt, 0, 0) \
283-
284-#define mips_emit_divu(rs, rt) \
285- mips_emit_special(divu, rs, rt, 0, 0) \
286-
287-#define mips_emit_madd(rs, rt) \
288- mips_emit_special(madd, rs, rt, 0, 0) \
289-
290-#define mips_emit_maddu(rs, rt) \
291- mips_emit_special(maddu, rs, rt, 0, 0) \
292-
293-#define mips_emit_movn(rd, rs, rt) \
294- mips_emit_special(movn, rs, rt, rd, 0) \
295-
296-#define mips_emit_movz(rd, rs, rt) \
297- mips_emit_special(movz, rs, rt, rd, 0) \
298-
299-#define mips_emit_lb(rt, rs, offset) \
300- mips_emit_imm(lb, rs, rt, offset) \
301-
302-#define mips_emit_lbu(rt, rs, offset) \
303- mips_emit_imm(lbu, rs, rt, offset) \
304-
305-#define mips_emit_lh(rt, rs, offset) \
306- mips_emit_imm(lh, rs, rt, offset) \
307-
308-#define mips_emit_lhu(rt, rs, offset) \
309- mips_emit_imm(lhu, rs, rt, offset) \
310-
311-#define mips_emit_lw(rt, rs, offset) \
312- mips_emit_imm(lw, rs, rt, offset) \
313-
314-#define mips_emit_sb(rt, rs, offset) \
315- mips_emit_imm(sb, rs, rt, offset) \
316-
317-#define mips_emit_sh(rt, rs, offset) \
318- mips_emit_imm(sh, rs, rt, offset) \
319-
320-#define mips_emit_sw(rt, rs, offset) \
321- mips_emit_imm(sw, rs, rt, offset) \
322-
323-#define mips_emit_lui(rt, imm) \
324- mips_emit_imm(lui, 0, rt, imm) \
325-
326-#define mips_emit_addiu(rt, rs, imm) \
327- mips_emit_imm(addiu, rs, rt, imm) \
328-
329-#define mips_emit_xori(rt, rs, imm) \
330- mips_emit_imm(xori, rs, rt, imm) \
331-
332-#define mips_emit_ori(rt, rs, imm) \
333- mips_emit_imm(ori, rs, rt, imm) \
334-
335-#define mips_emit_andi(rt, rs, imm) \
336- mips_emit_imm(andi, rs, rt, imm) \
337-
338-#define mips_emit_slti(rt, rs, imm) \
339- mips_emit_imm(slti, rs, rt, imm) \
340-
341-#define mips_emit_sltiu(rt, rs, imm) \
342- mips_emit_imm(sltiu, rs, rt, imm) \
343-
344-#define mips_emit_ext(rt, rs, pos, size) \
345- mips_emit_special3(ext, rs, rt, (size - 1), pos) \
346-
347-#define mips_emit_ins(rt, rs, pos, size) \
348- mips_emit_special3(ins, rs, rt, (pos + size - 1), pos) \
349-
350-// Breaks down if the backpatch offset is greater than 16bits, take care
351-// when using (should be okay if limited to conditional instructions)
352-
353-#define mips_emit_b_filler(type, rs, rt, writeback_location) \
354- (writeback_location) = translation_ptr; \
355- mips_emit_imm(type, rs, rt, 0) \
356-
357-// The backpatch code for this has to be handled differently than the above
358-
359-#define mips_emit_j_filler(writeback_location) \
360- (writeback_location) = translation_ptr; \
361- mips_emit_jump(j, 0) \
362-
363-#define mips_emit_b(type, rs, rt, offset) \
364- mips_emit_imm(type, rs, rt, offset) \
365-
366-#define mips_emit_j(offset) \
367- mips_emit_jump(j, offset) \
368-
369-#define mips_emit_jal(offset) \
370- mips_emit_jump(jal, offset) \
371-
372-#define mips_emit_jr(rs) \
373- mips_emit_special(jr, rs, 0, 0, 0) \
374-
375-#define mips_emit_bltzal(rs, offset) \
376- mips_emit_regimm(bltzal, rs, offset) \
377-
378-#define mips_emit_nop() \
379- mips_emit_sll(reg_zero, reg_zero, 0) \
380-
381-#define reg_base mips_reg_s0
382-#define reg_cycles mips_reg_s1
383-#define reg_a0 mips_reg_a0
384-#define reg_a1 mips_reg_a1
385-#define reg_a2 mips_reg_a2
386-#define reg_rv mips_reg_v0
387-#define reg_pc mips_reg_s3
388-#define reg_temp mips_reg_at
389-#define reg_zero mips_reg_zero
390-
391-#define reg_n_cache mips_reg_s4
392-#define reg_z_cache mips_reg_s5
393-#define reg_c_cache mips_reg_s6
394-#define reg_v_cache mips_reg_s7
395-
396-#define reg_r0 mips_reg_v1
397-#define reg_r1 mips_reg_a3
398-#define reg_r2 mips_reg_t0
399-#define reg_r3 mips_reg_t1
400-#define reg_r4 mips_reg_t2
401-#define reg_r5 mips_reg_t3
402-#define reg_r6 mips_reg_t4
403-#define reg_r7 mips_reg_t5
404-#define reg_r8 mips_reg_t6
405-#define reg_r9 mips_reg_t7
406-#define reg_r10 mips_reg_s2
407-#define reg_r11 mips_reg_t8
408-#define reg_r12 mips_reg_t9
409-#define reg_r13 mips_reg_gp
410-#define reg_r14 mips_reg_fp
411-
412-// Writing to r15 goes straight to a0, to be chained with other ops
413-
414-u32 arm_to_mips_reg[] =
415-{
416- reg_r0,
417- reg_r1,
418- reg_r2,
419- reg_r3,
420- reg_r4,
421- reg_r5,
422- reg_r6,
423- reg_r7,
424- reg_r8,
425- reg_r9,
426- reg_r10,
427- reg_r11,
428- reg_r12,
429- reg_r13,
430- reg_r14,
431- reg_a0,
432- reg_a1,
433- reg_a2,
434- reg_temp
435-};
436-
437-#define arm_reg_a0 15
438-#define arm_reg_a1 16
439-#define arm_reg_a2 17
440-#define arm_reg_temp 18
441-
442-#define generate_load_reg(ireg, reg_index) \
443- mips_emit_addu(ireg, arm_to_mips_reg[reg_index], reg_zero) \
444-
445-#define generate_load_imm(ireg, imm) \
446- if(((s32)imm >= -32768) && ((s32)imm <= 32767)) \
447- { \
448- mips_emit_addiu(ireg, reg_zero, imm); \
449- } \
450- else \
451- { \
452- if(((u32)imm >> 16) == 0x0000) \
453- { \
454- mips_emit_ori(ireg, reg_zero, imm); \
455- } \
456- else \
457- { \
458- mips_emit_lui(ireg, imm >> 16); \
459- \
460- if(((u32)imm & 0x0000FFFF) != 0x00000000) \
461- { \
462- mips_emit_ori(ireg, ireg, imm & 0xFFFF); \
463- } \
464- } \
465- } \
466-
467-#define generate_load_pc(ireg, new_pc) \
468-{ \
469- s32 pc_delta = new_pc - stored_pc; \
470- if((pc_delta >= -32768) && (pc_delta <= 32767)) \
471- { \
472- mips_emit_addiu(ireg, reg_pc, pc_delta); \
473- } \
474- else \
475- { \
476- generate_load_imm(ireg, new_pc); \
477- } \
478-} \
479-
480-#define generate_store_reg(ireg, reg_index) \
481- mips_emit_addu(arm_to_mips_reg[reg_index], ireg, reg_zero) \
482-
483-#define generate_shift_left(ireg, imm) \
484- mips_emit_sll(ireg, ireg, imm) \
485-
486-#define generate_shift_right(ireg, imm) \
487- mips_emit_srl(ireg, ireg, imm) \
488-
489-#define generate_shift_right_arithmetic(ireg, imm) \
490- mips_emit_sra(ireg, ireg, imm) \
491-
492-#define generate_rotate_right(ireg, imm) \
493- mips_emit_rotr(ireg, ireg, imm) \
494-
495-#define generate_add(ireg_dest, ireg_src) \
496- mips_emit_addu(ireg_dest, ireg_dest, ireg_src) \
497-
498-#define generate_sub(ireg_dest, ireg_src) \
499- mips_emit_subu(ireg_dest, ireg_dest, ireg_src) \
500-
501-#define generate_or(ireg_dest, ireg_src) \
502- mips_emit_or(ireg_dest, ireg_dest, ireg_src) \
503-
504-#define generate_xor(ireg_dest, ireg_src) \
505- mips_emit_xor(ireg_dest, ireg_dest, ireg_src) \
506-
507-#define generate_alu_imm(imm_type, reg_type, ireg_dest, ireg_src, imm) \
508- if(((s32)imm >= -32768) && ((s32)imm <= 32767)) \
509- { \
510- mips_emit_##imm_type(ireg_dest, ireg_src, imm); \
511- } \
512- else \
513- { \
514- generate_load_imm(reg_temp, imm); \
515- mips_emit_##reg_type(ireg_dest, ireg_src, reg_temp); \
516- } \
517-
518-#define generate_alu_immu(imm_type, reg_type, ireg_dest, ireg_src, imm) \
519- if(((u32)imm >= 0) && ((u32)imm <= 65535)) \
520- { \
521- mips_emit_##imm_type(ireg_dest, ireg_src, imm); \
522- } \
523- else \
524- { \
525- generate_load_imm(reg_temp, imm); \
526- mips_emit_##reg_type(ireg_dest, ireg_src, reg_temp); \
527- } \
528-
529-#define generate_add_imm(ireg, imm) \
530- generate_alu_imm(addiu, add, ireg, ireg, imm) \
531-
532-#define generate_sub_imm(ireg, imm) \
533- generate_alu_imm(addiu, add, ireg, ireg, -imm) \
534-
535-#define generate_xor_imm(ireg, imm) \
536- generate_alu_immu(xori, xor, ireg, ireg, imm) \
537-
538-#define generate_add_reg_reg_imm(ireg_dest, ireg_src, imm) \
539- generate_alu_imm(addiu, add, ireg_dest, ireg_src, imm) \
540-
541-#define generate_and_imm(ireg, imm) \
542- generate_alu_immu(andi, and, ireg, ireg, imm) \
543-
544-#define generate_mov(ireg_dest, ireg_src) \
545- mips_emit_addu(ireg_dest, ireg_src, reg_zero) \
546-
547-#define generate_multiply_s64() \
548- mips_emit_mult(arm_to_mips_reg[rm], arm_to_mips_reg[rs]) \
549-
550-#define generate_multiply_u64() \
551- mips_emit_multu(arm_to_mips_reg[rm], arm_to_mips_reg[rs]) \
552-
553-#define generate_multiply_s64_add() \
554- mips_emit_madd(arm_to_mips_reg[rm], arm_to_mips_reg[rs]) \
555-
556-#define generate_multiply_u64_add() \
557- mips_emit_maddu(arm_to_mips_reg[rm], arm_to_mips_reg[rs]) \
558-
559-#define generate_function_call(function_location) \
560- mips_emit_jal(mips_absolute_offset(function_location)); \
561- mips_emit_nop() \
562-
563-#define generate_function_call_swap_delay(function_location) \
564-{ \
565- u32 delay_instruction = ADDRESS32(translation_ptr, -4); \
566- translation_ptr -= 4; \
567- mips_emit_jal(mips_absolute_offset(function_location)); \
568- ADDRESS32(translation_ptr, 0) = delay_instruction; \
569- translation_ptr += 4; \
570-} \
571-
572-#define generate_swap_delay() \
573-{ \
574- u32 delay_instruction = ADDRESS32(translation_ptr, -8); \
575- u32 branch_instruction = ADDRESS32(translation_ptr, -4); \
576- branch_instruction = (branch_instruction & 0xFFFF0000) | \
577- (((branch_instruction & 0x0000FFFF) + 1) & 0x0000FFFF); \
578- ADDRESS32(translation_ptr, -8) = branch_instruction; \
579- ADDRESS32(translation_ptr, -4) = delay_instruction; \
580-} \
581-
582-#define generate_cycle_update() \
583- if(cycle_count != 0) \
584- { \
585- mips_emit_addiu(reg_cycles, reg_cycles, -cycle_count); \
586- cycle_count = 0; \
587- } \
588-
589-#define generate_cycle_update_force() \
590- mips_emit_addiu(reg_cycles, reg_cycles, -cycle_count); \
591- cycle_count = 0 \
592-
593-#define generate_branch_patch_conditional(dest, offset) \
594- *((u16 *)(dest)) = mips_relative_offset(dest, offset) \
595-
596-#define generate_branch_patch_unconditional(dest, offset) \
597- *((u32 *)(dest)) = (mips_opcode_j << 26) | \
598- ((mips_absolute_offset(offset)) & 0x3FFFFFF) \
599-
600-#define generate_branch_no_cycle_update(writeback_location, new_pc) \
601- { \
602- u8 i; \
603- u8 flag = 0; \
604- for( i = 0; i < idle_loop_targets; i++) \
605- if(pc == idle_loop_target_pc[i]) \
606- flag = 1; \
607- if(flag == 1) \
608- { \
609- generate_load_pc(reg_a0, new_pc); \
610- generate_function_call_swap_delay(mips_update_gba); \
611- mips_emit_j_filler(writeback_location); \
612- mips_emit_nop(); \
613- } \
614- else \
615- { \
616- generate_load_pc(reg_a0, new_pc); \
617- mips_emit_bltzal(reg_cycles, \
618- mips_relative_offset(translation_ptr, update_trampoline)); \
619- generate_swap_delay(); \
620- mips_emit_j_filler(writeback_location); \
621- mips_emit_nop(); \
622- } \
623- } \
624-
625-#define generate_branch_cycle_update(writeback_location, new_pc) \
626- generate_cycle_update(); \
627- generate_branch_no_cycle_update(writeback_location, new_pc) \
628-
629-#define generate_conditional_branch(ireg_a, ireg_b, type, writeback_location) \
630- generate_branch_filler_##type(ireg_a, ireg_b, writeback_location) \
631-
632-// a0 holds the destination
633-
634-#define generate_indirect_branch_cycle_update(type) \
635- mips_emit_j(mips_absolute_offset(mips_indirect_branch_##type)); \
636- generate_cycle_update_force() \
637-
638-#define generate_indirect_branch_no_cycle_update(type) \
639- mips_emit_j(mips_absolute_offset(mips_indirect_branch_##type)); \
640- mips_emit_nop() \
641-
642-#define generate_block_prologue() \
643- update_trampoline = translation_ptr; \
644- __asm__ \
645- ( \
646- "cache 8, 0(%0)\n" \
647- "cache 8, 0(%0)" : : "r"(translation_ptr) \
648- ); \
649- \
650- mips_emit_j(mips_absolute_offset(mips_update_gba)); \
651- mips_emit_nop(); \
652- generate_load_imm(reg_pc, stored_pc) \
653-
654-#define translate_invalidate_dcache() \
655- sceKernelDcacheWritebackAll() \
656-
657-#define block_prologue_size 8
658-
659-#define check_generate_n_flag \
660- (flag_status & 0x08) \
661-
662-#define check_generate_z_flag \
663- (flag_status & 0x04) \
664-
665-#define check_generate_c_flag \
666- (flag_status & 0x02) \
667-
668-#define check_generate_v_flag \
669- (flag_status & 0x01) \
670-
671-#define generate_load_reg_pc(ireg, reg_index, pc_offset) \
672- if(reg_index == REG_PC) \
673- { \
674- generate_load_pc(ireg, (pc + pc_offset)); \
675- } \
676- else \
677- { \
678- generate_load_reg(ireg, reg_index); \
679- } \
680-
681-#define check_load_reg_pc(arm_reg, reg_index, pc_offset) \
682- if(reg_index == REG_PC) \
683- { \
684- reg_index = arm_reg; \
685- generate_load_pc(arm_to_mips_reg[arm_reg], (pc + pc_offset)); \
686- } \
687-
688-#define check_store_reg_pc_no_flags(reg_index) \
689- if(reg_index == REG_PC) \
690- { \
691- generate_indirect_branch_arm(); \
692- } \
693-
694-#define check_store_reg_pc_flags(reg_index) \
695- if(reg_index == REG_PC) \
696- { \
697- generate_function_call(execute_spsr_restore); \
698- generate_indirect_branch_dual(); \
699- } \
700-
701-#define generate_shift_imm_lsl_no_flags(arm_reg, _rm, _shift) \
702- check_load_reg_pc(arm_reg, _rm, 8); \
703- if(_shift != 0) \
704- { \
705- mips_emit_sll(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], _shift); \
706- _rm = arm_reg; \
707- } \
708-
709-#define generate_shift_imm_lsr_no_flags(arm_reg, _rm, _shift) \
710- if(_shift != 0) \
711- { \
712- check_load_reg_pc(arm_reg, _rm, 8); \
713- mips_emit_srl(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], _shift); \
714- } \
715- else \
716- { \
717- mips_emit_addu(arm_to_mips_reg[arm_reg], reg_zero, reg_zero); \
718- } \
719- _rm = arm_reg \
720-
721-#define generate_shift_imm_asr_no_flags(arm_reg, _rm, _shift) \
722- check_load_reg_pc(arm_reg, _rm, 8); \
723- if(_shift != 0) \
724- { \
725- mips_emit_sra(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], _shift); \
726- } \
727- else \
728- { \
729- mips_emit_sra(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], 31); \
730- } \
731- _rm = arm_reg \
732-
733-#define generate_shift_imm_ror_no_flags(arm_reg, _rm, _shift) \
734- check_load_reg_pc(arm_reg, _rm, 8); \
735- if(_shift != 0) \
736- { \
737- mips_emit_rotr(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], _shift); \
738- } \
739- else \
740- { \
741- mips_emit_srl(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], 1); \
742- mips_emit_ins(arm_to_mips_reg[arm_reg], reg_c_cache, 31, 1); \
743- } \
744- _rm = arm_reg \
745-
746-#define generate_shift_imm_lsl_flags(arm_reg, _rm, _shift) \
747- check_load_reg_pc(arm_reg, _rm, 8); \
748- if(_shift != 0) \
749- { \
750- mips_emit_ext(reg_c_cache, arm_to_mips_reg[_rm], (32 - _shift), 1); \
751- mips_emit_sll(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], _shift); \
752- _rm = arm_reg; \
753- } \
754-
755-#define generate_shift_imm_lsr_flags(arm_reg, _rm, _shift) \
756- check_load_reg_pc(arm_reg, _rm, 8); \
757- if(_shift != 0) \
758- { \
759- mips_emit_ext(reg_c_cache, arm_to_mips_reg[_rm], (_shift - 1), 1); \
760- mips_emit_srl(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], _shift); \
761- } \
762- else \
763- { \
764- mips_emit_srl(reg_c_cache, arm_to_mips_reg[_rm], 31); \
765- mips_emit_addu(arm_to_mips_reg[arm_reg], reg_zero, reg_zero); \
766- } \
767- _rm = arm_reg \
768-
769-#define generate_shift_imm_asr_flags(arm_reg, _rm, _shift) \
770- check_load_reg_pc(arm_reg, _rm, 8); \
771- if(_shift != 0) \
772- { \
773- mips_emit_ext(reg_c_cache, arm_to_mips_reg[_rm], (_shift - 1), 1); \
774- mips_emit_sra(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], _shift); \
775- } \
776- else \
777- { \
778- mips_emit_sra(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], 31); \
779- mips_emit_andi(reg_c_cache, arm_to_mips_reg[arm_reg], 1); \
780- } \
781- _rm = arm_reg \
782-
783-#define generate_shift_imm_ror_flags(arm_reg, _rm, _shift) \
784- check_load_reg_pc(arm_reg, _rm, 8); \
785- if(_shift != 0) \
786- { \
787- mips_emit_ext(reg_c_cache, arm_to_mips_reg[_rm], (_shift - 1), 1); \
788- mips_emit_rotr(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], _shift); \
789- } \
790- else \
791- { \
792- mips_emit_andi(reg_temp, arm_to_mips_reg[_rm], 1); \
793- mips_emit_srl(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], 1); \
794- mips_emit_ins(arm_to_mips_reg[arm_reg], reg_c_cache, 31, 1); \
795- mips_emit_addu(reg_c_cache, reg_temp, reg_zero); \
796- } \
797- _rm = arm_reg \
798-
799-#define generate_shift_reg_lsl_no_flags(_rm, _rs) \
800- mips_emit_sltiu(reg_temp, arm_to_mips_reg[_rs], 32); \
801- mips_emit_sllv(reg_a0, arm_to_mips_reg[_rm], arm_to_mips_reg[_rs]); \
802- mips_emit_movz(reg_a0, reg_zero, reg_temp) \
803-
804-#define generate_shift_reg_lsr_no_flags(_rm, _rs) \
805- mips_emit_sltiu(reg_temp, arm_to_mips_reg[_rs], 32); \
806- mips_emit_srlv(reg_a0, arm_to_mips_reg[_rm], arm_to_mips_reg[_rs]); \
807- mips_emit_movz(reg_a0, reg_zero, reg_temp) \
808-
809-#define generate_shift_reg_asr_no_flags(_rm, _rs) \
810- mips_emit_sltiu(reg_temp, arm_to_mips_reg[_rs], 32); \
811- mips_emit_b(bne, reg_temp, reg_zero, 2); \
812- mips_emit_srav(reg_a0, arm_to_mips_reg[_rm], arm_to_mips_reg[_rs]); \
813- mips_emit_sra(reg_a0, reg_a0, 31) \
814-
815-#define generate_shift_reg_ror_no_flags(_rm, _rs) \
816- mips_emit_rotrv(reg_a0, arm_to_mips_reg[_rm], arm_to_mips_reg[_rs]) \
817-
818-#define generate_shift_reg_lsl_flags(_rm, _rs) \
819- generate_load_reg_pc(reg_a0, _rm, 12); \
820- generate_load_reg_pc(reg_a1, _rs, 8); \
821- generate_function_call_swap_delay(execute_lsl_flags_reg) \
822-
823-#define generate_shift_reg_lsr_flags(_rm, _rs) \
824- generate_load_reg_pc(reg_a0, _rm, 12); \
825- generate_load_reg_pc(reg_a1, _rs, 8); \
826- generate_function_call_swap_delay(execute_lsr_flags_reg) \
827-
828-#define generate_shift_reg_asr_flags(_rm, _rs) \
829- generate_load_reg_pc(reg_a0, _rm, 12); \
830- generate_load_reg_pc(reg_a1, _rs, 8); \
831- generate_function_call_swap_delay(execute_asr_flags_reg) \
832-
833-#define generate_shift_reg_ror_flags(_rm, _rs) \
834- mips_emit_b(beq, arm_to_mips_reg[_rs], reg_zero, 3); \
835- mips_emit_addiu(reg_temp, arm_to_mips_reg[_rs], -1); \
836- mips_emit_srlv(reg_temp, arm_to_mips_reg[_rm], reg_temp); \
837- mips_emit_andi(reg_c_cache, reg_temp, 1); \
838- mips_emit_rotrv(reg_a0, arm_to_mips_reg[_rm], arm_to_mips_reg[_rs]) \
839-
840-#define generate_shift_imm(arm_reg, name, flags_op) \
841- u32 shift = (opcode >> 7) & 0x1F; \
842- generate_shift_imm_##name##_##flags_op(arm_reg, rm, shift) \
843-
844-#define generate_shift_reg(arm_reg, name, flags_op) \
845- u32 rs = ((opcode >> 8) & 0x0F); \
846- generate_shift_reg_##name##_##flags_op(rm, rs); \
847- rm = arm_reg \
848-
849-// Made functions due to the macro expansion getting too large.
850-// Returns a new rm if it redirects it (which will happen on most of these
851-// cases)
852-
853-#define generate_load_rm_sh_builder(flags_op) \
854-u32 generate_load_rm_sh_##flags_op(u32 rm) \
855-{ \
856- switch((opcode >> 4) & 0x07) \
857- { \
858- /* LSL imm */ \
859- case 0x0: \
860- { \
861- generate_shift_imm(arm_reg_a0, lsl, flags_op); \
862- break; \
863- } \
864- \
865- /* LSL reg */ \
866- case 0x1: \
867- { \
868- generate_shift_reg(arm_reg_a0, lsl, flags_op); \
869- break; \
870- } \
871- \
872- /* LSR imm */ \
873- case 0x2: \
874- { \
875- generate_shift_imm(arm_reg_a0, lsr, flags_op); \
876- break; \
877- } \
878- \
879- /* LSR reg */ \
880- case 0x3: \
881- { \
882- generate_shift_reg(arm_reg_a0, lsr, flags_op); \
883- break; \
884- } \
885- \
886- /* ASR imm */ \
887- case 0x4: \
888- { \
889- generate_shift_imm(arm_reg_a0, asr, flags_op); \
890- break; \
891- } \
892- \
893- /* ASR reg */ \
894- case 0x5: \
895- { \
896- generate_shift_reg(arm_reg_a0, asr, flags_op); \
897- break; \
898- } \
899- \
900- /* ROR imm */ \
901- case 0x6: \
902- { \
903- generate_shift_imm(arm_reg_a0, ror, flags_op); \
904- break; \
905- } \
906- \
907- /* ROR reg */ \
908- case 0x7: \
909- { \
910- generate_shift_reg(arm_reg_a0, ror, flags_op); \
911- break; \
912- } \
913- } \
914- \
915- return rm; \
916-} \
917-
918-#define read_memory_constant_u8(address) \
919- read_memory8(address) \
920-
921-#define read_memory_constant_u16(address) \
922- read_memory16(address) \
923-
924-#define read_memory_constant_u32(address) \
925- read_memory32(address) \
926-
927-#define read_memory_constant_s8(address) \
928- (s8)read_memory8(address) \
929-
930-#define read_memory_constant_s16(address) \
931- (s16)read_memory16_signed(address) \
932-
933-#define generate_load_memory_u8(ireg, offset) \
934- mips_emit_lbu(ireg, ireg, offset) \
935-
936-#define generate_load_memory_u16(ireg, offset) \
937- mips_emit_lhu(ireg, ireg, offset) \
938-
939-#define generate_load_memory_u32(ireg, offset) \
940- mips_emit_lw(ireg, ireg, offset) \
941-
942-#define generate_load_memory_s8(ireg, offset) \
943- mips_emit_lb(ireg, ireg, offset) \
944-
945-#define generate_load_memory_s16(ireg, offset) \
946- mips_emit_lh(ireg, ireg, offset) \
947-
948-#define generate_load_memory(type, ireg, address) \
949-{ \
950- u32 _address = (u32)(address); \
951- u32 _address_hi = (_address + 0x8000) >> 16; \
952- generate_load_imm(ireg, address); \
953- mips_emit_lui(ireg, _address_hi >> 16); \
954- generate_load_memory_##type(ireg, _address - (_address_hi << 16)); \
955-} \
956-
957-#define generate_block_extra_vars() \
958- u32 stored_pc = pc; \
959- u8 *update_trampoline \
960-
961-#define generate_block_extra_vars_arm() \
962- generate_block_extra_vars(); \
963- \
964- auto u32 generate_load_rm_sh_flags(u32 rm); \
965- auto u32 generate_load_rm_sh_no_flags(u32 rm); \
966- auto u32 generate_load_offset_sh(u32 rm); \
967- auto void generate_indirect_branch_arm(); \
968- auto void generate_indirect_branch_dual(); \
969- \
970- generate_load_rm_sh_builder(flags); \
971- generate_load_rm_sh_builder(no_flags); \
972- \
973- u32 generate_load_offset_sh(u32 rm) \
974- { \
975- switch((opcode >> 5) & 0x03) \
976- { \
977- /* LSL imm */ \
978- case 0x0: \
979- { \
980- generate_shift_imm(arm_reg_a1, lsl, no_flags); \
981- break; \
982- } \
983- \
984- /* LSR imm */ \
985- case 0x1: \
986- { \
987- generate_shift_imm(arm_reg_a1, lsr, no_flags); \
988- break; \
989- } \
990- \
991- /* ASR imm */ \
992- case 0x2: \
993- { \
994- generate_shift_imm(arm_reg_a1, asr, no_flags); \
995- break; \
996- } \
997- \
998- /* ROR imm */ \
999- case 0x3: \
1000- { \
1001- generate_shift_imm(arm_reg_a1, ror, no_flags); \
1002- break; \
1003- } \
1004- } \
1005- \
1006- return rm; \
1007- } \
1008- \
1009- void generate_indirect_branch_arm() \
1010- { \
1011- if(condition == 0x0E) \
1012- { \
1013- generate_indirect_branch_cycle_update(arm); \
1014- } \
1015- else \
1016- { \
1017- generate_indirect_branch_no_cycle_update(arm); \
1018- } \
1019- } \
1020- \
1021- void generate_indirect_branch_dual() \
1022- { \
1023- if(condition == 0x0E) \
1024- { \
1025- generate_indirect_branch_cycle_update(dual); \
1026- } \
1027- else \
1028- { \
1029- generate_indirect_branch_no_cycle_update(dual); \
1030- } \
1031- } \
1032-
1033-#define generate_block_extra_vars_thumb() \
1034- generate_block_extra_vars() \
1035-
1036-// It should be okay to still generate result flags, spsr will overwrite them.
1037-// This is pretty infrequent (returning from interrupt handlers, et al) so
1038-// probably not worth optimizing for.
1039-
1040-u32 execute_spsr_restore_body(u32 address)
1041-{
1042- set_cpu_mode(cpu_modes[reg[REG_CPSR] & 0x1F]);
1043- if((io_registers[REG_IE] & io_registers[REG_IF]) &&
1044- io_registers[REG_IME] && ((reg[REG_CPSR] & 0x80) == 0))
1045- {
1046- reg_mode[MODE_IRQ][6] = address + 4;
1047- spsr[MODE_IRQ] = reg[REG_CPSR];
1048- reg[REG_CPSR] = 0xD2;
1049- address = 0x00000018;
1050- set_cpu_mode(MODE_IRQ);
1051- }
1052-
1053- if(reg[REG_CPSR] & 0x20)
1054- address |= 0x01;
1055-
1056- return address;
1057-}
1058-
1059-typedef enum
1060-{
1061- CONDITION_TRUE,
1062- CONDITION_FALSE,
1063- CONDITION_EQUAL,
1064- CONDITION_NOT_EQUAL
1065-} condition_check_type;
1066-
1067-
1068-#define generate_condition_eq() \
1069- mips_emit_b_filler(beq, reg_z_cache, reg_zero, backpatch_address); \
1070- generate_cycle_update_force() \
1071-
1072-#define generate_condition_ne() \
1073- mips_emit_b_filler(bne, reg_z_cache, reg_zero, backpatch_address); \
1074- generate_cycle_update_force() \
1075-
1076-#define generate_condition_cs() \
1077- mips_emit_b_filler(beq, reg_c_cache, reg_zero, backpatch_address); \
1078- generate_cycle_update_force() \
1079-
1080-#define generate_condition_cc() \
1081- mips_emit_b_filler(bne, reg_c_cache, reg_zero, backpatch_address); \
1082- generate_cycle_update_force() \
1083-
1084-#define generate_condition_mi() \
1085- mips_emit_b_filler(beq, reg_n_cache, reg_zero, backpatch_address); \
1086- generate_cycle_update_force() \
1087-
1088-#define generate_condition_pl() \
1089- mips_emit_b_filler(bne, reg_n_cache, reg_zero, backpatch_address); \
1090- generate_cycle_update_force() \
1091-
1092-#define generate_condition_vs() \
1093- mips_emit_b_filler(beq, reg_v_cache, reg_zero, backpatch_address); \
1094- generate_cycle_update_force() \
1095-
1096-#define generate_condition_vc() \
1097- mips_emit_b_filler(bne, reg_v_cache, reg_zero, backpatch_address); \
1098- generate_cycle_update_force() \
1099-
1100-#define generate_condition_hi() \
1101- mips_emit_xori(reg_temp, reg_c_cache, 1); \
1102- mips_emit_or(reg_temp, reg_temp, reg_z_cache); \
1103- mips_emit_b_filler(bne, reg_temp, reg_zero, backpatch_address); \
1104- generate_cycle_update_force() \
1105-
1106-#define generate_condition_ls() \
1107- mips_emit_xori(reg_temp, reg_c_cache, 1); \
1108- mips_emit_or(reg_temp, reg_temp, reg_z_cache); \
1109- mips_emit_b_filler(beq, reg_temp, reg_zero, backpatch_address); \
1110- generate_cycle_update_force() \
1111-
1112-#define generate_condition_ge() \
1113- mips_emit_b_filler(bne, reg_n_cache, reg_v_cache, backpatch_address); \
1114- generate_cycle_update_force() \
1115-
1116-#define generate_condition_lt() \
1117- mips_emit_b_filler(beq, reg_n_cache, reg_v_cache, backpatch_address); \
1118- generate_cycle_update_force() \
1119-
1120-#define generate_condition_gt() \
1121- mips_emit_xor(reg_temp, reg_n_cache, reg_v_cache); \
1122- mips_emit_or(reg_temp, reg_temp, reg_z_cache); \
1123- mips_emit_b_filler(bne, reg_temp, reg_zero, backpatch_address); \
1124- generate_cycle_update_force() \
1125-
1126-#define generate_condition_le() \
1127- mips_emit_xor(reg_temp, reg_n_cache, reg_v_cache); \
1128- mips_emit_or(reg_temp, reg_temp, reg_z_cache); \
1129- mips_emit_b_filler(beq, reg_temp, reg_zero, backpatch_address); \
1130- generate_cycle_update_force() \
1131-
1132-#define generate_condition() \
1133- switch(condition) \
1134- { \
1135- case 0x0: \
1136- generate_condition_eq(); \
1137- break; \
1138- \
1139- case 0x1: \
1140- generate_condition_ne(); \
1141- break; \
1142- \
1143- case 0x2: \
1144- generate_condition_cs(); \
1145- break; \
1146- \
1147- case 0x3: \
1148- generate_condition_cc(); \
1149- break; \
1150- \
1151- case 0x4: \
1152- generate_condition_mi(); \
1153- break; \
1154- \
1155- case 0x5: \
1156- generate_condition_pl(); \
1157- break; \
1158- \
1159- case 0x6: \
1160- generate_condition_vs(); \
1161- break; \
1162- \
1163- case 0x7: \
1164- generate_condition_vc(); \
1165- break; \
1166- \
1167- case 0x8: \
1168- generate_condition_hi(); \
1169- break; \
1170- \
1171- case 0x9: \
1172- generate_condition_ls(); \
1173- break; \
1174- \
1175- case 0xA: \
1176- generate_condition_ge(); \
1177- break; \
1178- \
1179- case 0xB: \
1180- generate_condition_lt(); \
1181- break; \
1182- \
1183- case 0xC: \
1184- generate_condition_gt(); \
1185- break; \
1186- \
1187- case 0xD: \
1188- generate_condition_le(); \
1189- break; \
1190- \
1191- case 0xE: \
1192- break; \
1193- \
1194- case 0xF: \
1195- break; \
1196- } \
1197-
1198-#define generate_branch() \
1199-{ \
1200- if(condition == 0x0E) \
1201- { \
1202- generate_branch_cycle_update( \
1203- block_exits[block_exit_position].branch_source, \
1204- block_exits[block_exit_position].branch_target); \
1205- } \
1206- else \
1207- { \
1208- generate_branch_no_cycle_update( \
1209- block_exits[block_exit_position].branch_source, \
1210- block_exits[block_exit_position].branch_target); \
1211- } \
1212- block_exit_position++; \
1213-} \
1214-
1215-#define generate_op_and_reg(_rd, _rn, _rm) \
1216- mips_emit_and(_rd, _rn, _rm) \
1217-
1218-#define generate_op_orr_reg(_rd, _rn, _rm) \
1219- mips_emit_or(_rd, _rn, _rm) \
1220-
1221-#define generate_op_eor_reg(_rd, _rn, _rm) \
1222- mips_emit_xor(_rd, _rn, _rm) \
1223-
1224-#define generate_op_bic_reg(_rd, _rn, _rm) \
1225- mips_emit_nor(reg_temp, _rm, reg_zero); \
1226- mips_emit_and(_rd, _rn, reg_temp) \
1227-
1228-#define generate_op_sub_reg(_rd, _rn, _rm) \
1229- mips_emit_subu(_rd, _rn, _rm) \
1230-
1231-#define generate_op_rsb_reg(_rd, _rn, _rm) \
1232- mips_emit_subu(_rd, _rm, _rn) \
1233-
1234-#define generate_op_sbc_reg(_rd, _rn, _rm) \
1235- mips_emit_subu(_rd, _rn, _rm); \
1236- mips_emit_xori(reg_temp, reg_c_cache, 1); \
1237- mips_emit_subu(_rd, _rd, reg_temp) \
1238-
1239-#define generate_op_rsc_reg(_rd, _rn, _rm) \
1240- mips_emit_subu(_rd, _rm, _rn); \
1241- mips_emit_xori(reg_temp, reg_c_cache, 1); \
1242- mips_emit_subu(_rd, _rd, reg_temp) \
1243-
1244-#define generate_op_add_reg(_rd, _rn, _rm) \
1245- mips_emit_addu(_rd, _rn, _rm) \
1246-
1247-#define generate_op_adc_reg(_rd, _rn, _rm) \
1248- mips_emit_addu(reg_temp, _rm, reg_c_cache); \
1249- mips_emit_addu(_rd, _rn, reg_temp) \
1250-
1251-#define generate_op_mov_reg(_rd, _rn, _rm) \
1252- mips_emit_addu(_rd, _rm, reg_zero) \
1253-
1254-#define generate_op_mvn_reg(_rd, _rn, _rm) \
1255- mips_emit_nor(_rd, _rm, reg_zero) \
1256-
1257-#define generate_op_imm_wrapper(name, _rd, _rn) \
1258- if(imm != 0) \
1259- { \
1260- generate_load_imm(reg_a0, imm); \
1261- generate_op_##name##_reg(_rd, _rn, reg_a0); \
1262- } \
1263- else \
1264- { \
1265- generate_op_##name##_reg(_rd, _rn, reg_zero); \
1266- } \
1267-
1268-#define generate_op_and_imm(_rd, _rn) \
1269- generate_alu_immu(andi, and, _rd, _rn, imm) \
1270-
1271-#define generate_op_orr_imm(_rd, _rn) \
1272- generate_alu_immu(ori, or, _rd, _rn, imm) \
1273-
1274-#define generate_op_eor_imm(_rd, _rn) \
1275- generate_alu_immu(xori, xor, _rd, _rn, imm) \
1276-
1277-#define generate_op_bic_imm(_rd, _rn) \
1278- generate_alu_immu(andi, and, _rd, _rn, (~imm)) \
1279-
1280-#define generate_op_sub_imm(_rd, _rn) \
1281- generate_alu_imm(addiu, addu, _rd, _rn, (-imm)) \
1282-
1283-#define generate_op_rsb_imm(_rd, _rn) \
1284- if(imm != 0) \
1285- { \
1286- generate_load_imm(reg_temp, imm); \
1287- mips_emit_subu(_rd, reg_temp, _rn); \
1288- } \
1289- else \
1290- { \
1291- mips_emit_subu(_rd, reg_zero, _rn); \
1292- } \
1293-
1294-#define generate_op_sbc_imm(_rd, _rn) \
1295- generate_op_imm_wrapper(sbc, _rd, _rn) \
1296-
1297-#define generate_op_rsc_imm(_rd, _rn) \
1298- generate_op_imm_wrapper(rsc, _rd, _rn) \
1299-
1300-#define generate_op_add_imm(_rd, _rn) \
1301- generate_alu_imm(addiu, addu, _rd, _rn, imm) \
1302-
1303-#define generate_op_adc_imm(_rd, _rn) \
1304- generate_op_imm_wrapper(adc, _rd, _rn) \
1305-
1306-#define generate_op_mov_imm(_rd, _rn) \
1307- generate_load_imm(_rd, imm) \
1308-
1309-#define generate_op_mvn_imm(_rd, _rn) \
1310- generate_load_imm(_rd, (~imm)) \
1311-
1312-// フラグの変更 TODO
1313-// 論理演算
1314-// Vフラグは変化しない
1315-#define generate_op_logic_flags(_rd) \
1316- if(check_generate_n_flag) \
1317- { \
1318- mips_emit_srl(reg_n_cache, _rd, 31); \
1319- } \
1320- if(check_generate_z_flag) \
1321- { \
1322- mips_emit_sltiu(reg_z_cache, _rd, 1); \
1323- } \
1324-
1325-#define generate_op_sub_flags_prologue(_rn, _rm) \
1326- if(check_generate_c_flag) \
1327- { \
1328- mips_emit_sltu(reg_c_cache, _rn, _rm); \
1329- mips_emit_xori(reg_c_cache, reg_c_cache, 1); \
1330- } \
1331- if(check_generate_v_flag) \
1332- { \
1333- mips_emit_slt(reg_v_cache, _rn, _rm); \
1334- } \
1335-
1336-#define generate_op_sub_flags_epilogue(_rd) \
1337- generate_op_logic_flags(_rd); \
1338- if(check_generate_v_flag) \
1339- { \
1340- if(!check_generate_n_flag) \
1341- { \
1342- mips_emit_srl(reg_n_cache, _rd, 31); \
1343- } \
1344- mips_emit_xor(reg_v_cache, reg_v_cache, reg_n_cache); \
1345- } \
1346-
1347-#define generate_add_flags_prologue(_rn, _rm) \
1348- if(check_generate_c_flag | check_generate_v_flag) \
1349- { \
1350- mips_emit_addu(reg_c_cache, _rn, reg_zero); \
1351- } \
1352- if(check_generate_v_flag) \
1353- { \
1354- mips_emit_slt(reg_v_cache, _rm, reg_zero); \
1355- } \
1356-
1357-#define generate_add_flags_epilogue(_rd) \
1358- if(check_generate_v_flag) \
1359- { \
1360- mips_emit_slt(reg_a0, _rd, reg_c_cache); \
1361- mips_emit_xor(reg_v_cache, reg_v_cache, reg_a0); \
1362- } \
1363- if(check_generate_c_flag) \
1364- { \
1365- mips_emit_sltu(reg_c_cache, _rd, reg_c_cache); \
1366- } \
1367- generate_op_logic_flags(_rd) \
1368-
1369-#define generate_op_ands_reg(_rd, _rn, _rm) \
1370- mips_emit_and(_rd, _rn, _rm); \
1371- generate_op_logic_flags(_rd) \
1372-
1373-#define generate_op_orrs_reg(_rd, _rn, _rm) \
1374- mips_emit_or(_rd, _rn, _rm); \
1375- generate_op_logic_flags(_rd) \
1376-
1377-#define generate_op_eors_reg(_rd, _rn, _rm) \
1378- mips_emit_xor(_rd, _rn, _rm); \
1379- generate_op_logic_flags(_rd) \
1380-
1381-#define generate_op_bics_reg(_rd, _rn, _rm) \
1382- mips_emit_nor(reg_temp, _rm, reg_zero); \
1383- mips_emit_and(_rd, _rn, reg_temp); \
1384- generate_op_logic_flags(_rd) \
1385-
1386-#define generate_op_subs_reg(_rd, _rn, _rm) \
1387- generate_op_sub_flags_prologue(_rn, _rm); \
1388- mips_emit_subu(_rd, _rn, _rm); \
1389- generate_op_sub_flags_epilogue(_rd) \
1390-
1391-#define generate_op_rsbs_reg(_rd, _rn, _rm) \
1392- generate_op_sub_flags_prologue(_rm, _rn); \
1393- mips_emit_subu(_rd, _rm, _rn); \
1394- generate_op_sub_flags_epilogue(_rd) \
1395-
1396-#define generate_op_sbcs_reg(_rd, _rn, _rm) \
1397- mips_emit_xori(reg_temp, reg_c_cache, 1); \
1398- mips_emit_addu(reg_temp, _rm, reg_temp); \
1399- generate_op_sub_flags_prologue(_rn, reg_temp); \
1400- mips_emit_subu(_rd, _rn, reg_temp); \
1401- generate_op_sub_flags_epilogue(_rd) \
1402-
1403-#define generate_op_rscs_reg(_rd, _rn, _rm) \
1404- mips_emit_xori(reg_temp, reg_c_cache, 1); \
1405- mips_emit_addu(reg_temp, _rn, reg_temp); \
1406- generate_op_sub_flags_prologue(_rm, reg_temp); \
1407- mips_emit_subu(_rd, _rm, reg_temp); \
1408- generate_op_sub_flags_epilogue(_rd) \
1409-
1410-#define generate_op_adds_reg(_rd, _rn, _rm) \
1411- generate_add_flags_prologue(_rn, _rm); \
1412- mips_emit_addu(_rd, _rn, _rm); \
1413- generate_add_flags_epilogue(_rd) \
1414-
1415-#define generate_op_adcs_reg(_rd, _rn, _rm) \
1416- mips_emit_addu(reg_temp, _rm, reg_c_cache); \
1417- generate_add_flags_prologue(_rn, reg_temp); \
1418- mips_emit_addu(_rd, _rn, reg_temp); \
1419- generate_add_flags_epilogue(_rd) \
1420-
1421-#define generate_op_movs_reg(_rd, _rn, _rm) \
1422- mips_emit_addu(_rd, _rm, reg_zero); \
1423- generate_op_logic_flags(_rd) \
1424-
1425-#define generate_op_mvns_reg(_rd, _rn, _rm) \
1426- mips_emit_nor(_rd, _rm, reg_zero); \
1427- generate_op_logic_flags(_rd) \
1428-
1429-#define generate_op_neg_reg(_rd, _rn, _rm) \
1430- generate_op_subs_reg(_rd, reg_zero, _rm) \
1431-
1432-#define generate_op_muls_reg(_rd, _rn, _rm) \
1433- mips_emit_multu(_rn, _rm); \
1434- mips_emit_mflo(_rd); \
1435- generate_op_logic_flags(_rd) \
1436-
1437-#define generate_op_cmp_reg(_rd, _rn, _rm) \
1438- generate_op_subs_reg(reg_temp, _rn, _rm) \
1439-
1440-#define generate_op_cmn_reg(_rd, _rn, _rm) \
1441- generate_op_adds_reg(reg_temp, _rn, _rm) \
1442-
1443-#define generate_op_tst_reg(_rd, _rn, _rm) \
1444- generate_op_ands_reg(reg_temp, _rn, _rm) \
1445-
1446-#define generate_op_teq_reg(_rd, _rn, _rm) \
1447- generate_op_eors_reg(reg_temp, _rn, _rm) \
1448-
1449-#define generate_op_ands_imm(_rd, _rn) \
1450- generate_alu_immu(andi, and, _rd, _rn, imm); \
1451- generate_op_logic_flags(_rd) \
1452-
1453-#define generate_op_orrs_imm(_rd, _rn) \
1454- generate_alu_immu(ori, or, _rd, _rn, imm); \
1455- generate_op_logic_flags(_rd) \
1456-
1457-#define generate_op_eors_imm(_rd, _rn) \
1458- generate_alu_immu(xori, xor, _rd, _rn, imm); \
1459- generate_op_logic_flags(_rd) \
1460-
1461-#define generate_op_bics_imm(_rd, _rn) \
1462- generate_alu_immu(andi, and, _rd, _rn, (~imm)); \
1463- generate_op_logic_flags(_rd) \
1464-
1465-#define generate_op_subs_imm(_rd, _rn) \
1466- generate_op_imm_wrapper(subs, _rd, _rn) \
1467-
1468-#define generate_op_rsbs_imm(_rd, _rn) \
1469- generate_op_imm_wrapper(rsbs, _rd, _rn) \
1470-
1471-#define generate_op_sbcs_imm(_rd, _rn) \
1472- generate_op_imm_wrapper(sbcs, _rd, _rn) \
1473-
1474-#define generate_op_rscs_imm(_rd, _rn) \
1475- generate_op_imm_wrapper(rscs, _rd, _rn) \
1476-
1477-#define generate_op_adds_imm(_rd, _rn) \
1478- generate_op_imm_wrapper(adds, _rd, _rn) \
1479-
1480-#define generate_op_adcs_imm(_rd, _rn) \
1481- generate_op_imm_wrapper(adcs, _rd, _rn) \
1482-
1483-#define generate_op_movs_imm(_rd, _rn) \
1484- generate_load_imm(_rd, imm); \
1485- generate_op_logic_flags(_rd) \
1486-
1487-#define generate_op_mvns_imm(_rd, _rn) \
1488- generate_load_imm(_rd, (~imm)); \
1489- generate_op_logic_flags(_rd) \
1490-
1491-#define generate_op_cmp_imm(_rd, _rn) \
1492- generate_op_imm_wrapper(cmp, _rd, _rn) \
1493-
1494-#define generate_op_cmn_imm(_rd, _rn) \
1495- generate_op_imm_wrapper(cmn, _rd, _rn) \
1496-
1497-#define generate_op_tst_imm(_rd, _rn) \
1498- generate_op_ands_imm(reg_temp, _rn) \
1499-
1500-#define generate_op_teq_imm(_rd, _rn) \
1501- generate_op_eors_imm(reg_temp, _rn) \
1502-
1503-#define arm_generate_op_load_yes() \
1504- generate_load_reg_pc(reg_a1, rn, 8) \
1505-
1506-#define arm_generate_op_load_no() \
1507-
1508-#define arm_op_check_yes() \
1509- check_load_reg_pc(arm_reg_a1, rn, 8) \
1510-
1511-#define arm_op_check_no() \
1512-
1513-#define arm_generate_op_reg_flags(name, load_op) \
1514- arm_decode_data_proc_reg(); \
1515- if(check_generate_c_flag) \
1516- { \
1517- rm = generate_load_rm_sh_flags(rm); \
1518- } \
1519- else \
1520- { \
1521- rm = generate_load_rm_sh_no_flags(rm); \
1522- } \
1523- \
1524- arm_op_check_##load_op(); \
1525- generate_op_##name##_reg(arm_to_mips_reg[rd], arm_to_mips_reg[rn], \
1526- arm_to_mips_reg[rm]) \
1527-
1528-#define arm_generate_op_reg(name, load_op) \
1529- arm_decode_data_proc_reg(); \
1530- rm = generate_load_rm_sh_no_flags(rm); \
1531- arm_op_check_##load_op(); \
1532- generate_op_##name##_reg(arm_to_mips_reg[rd], arm_to_mips_reg[rn], \
1533- arm_to_mips_reg[rm]) \
1534-
1535-#define arm_generate_op_imm(name, load_op) \
1536- arm_decode_data_proc_imm(); \
1537- arm_op_check_##load_op(); \
1538- generate_op_##name##_imm(arm_to_mips_reg[rd], arm_to_mips_reg[rn]) \
1539-
1540-#define arm_generate_op_imm_flags(name, load_op) \
1541- arm_generate_op_imm(name, load_op) \
1542-
1543-
1544-/* 1S+x+y */
1545-/* x=1I cycles if Op2 shifted-by-register. y=1S+1N cycles if Rd=R15. */
1546-#define cycle_arm_data_proc_reg() \
1547- cycle_count++; \
1548- if(rd == reg_pc) \
1549- cycle_count += 2 \
1550-
1551-#define cycle_arm_data_proc_reg_flags() \
1552- cycle_arm_data_proc_reg() \
1553-
1554-#define cycle_arm_data_proc_imm() \
1555- if(rd == reg_pc) \
1556- cycle_count += 2 \
1557-
1558-#define cycle_arm_data_proc_imm_flags() \
1559- cycle_arm_data_proc_imm() \
1560-
1561-/* 1S+x */
1562-#define cycle_arm_data_proc_test_reg() \
1563- cycle_count++ \
1564-
1565-#define cycle_arm_data_proc_test_reg_flags() \
1566- cycle_arm_data_proc_test_reg() \
1567-
1568-#define cycle_arm_data_proc_test_imm() \
1569-
1570-#define cycle_arm_data_proc_test_imm_flags() \
1571-
1572-/* AND, EOR, SUB, RSB, ADD, ADC, SBC, RSC, ORR, BIC 1S+x+y */
1573-#define arm_data_proc(name, type, flags_op) \
1574-{ \
1575- arm_generate_op_##type(name, yes); \
1576- cycle_arm_data_proc_##type(); \
1577- check_store_reg_pc_##flags_op(rd); \
1578-} \
1579-
1580-/* TST, TEQ, CMP, CMN 1S+x */
1581-#define arm_data_proc_test(name, type) \
1582-{ \
1583- arm_generate_op_##type(name, yes); \
1584- cycle_arm_data_proc_test_##type(); \
1585-} \
1586-
1587-/* MOV, MVN 1S+x+y */
1588-#define arm_data_proc_unary(name, type, flags_op) \
1589-{ \
1590- arm_generate_op_##type(name, no); \
1591- cycle_arm_data_proc_##type(); \
1592- check_store_reg_pc_##flags_op(rd); \
1593-} \
1594-
1595-#define arm_multiply_flags_yes(_rd) \
1596- generate_op_logic_flags(_rd) \
1597-
1598-#define arm_multiply_flags_no(_rd) \
1599-
1600-#define arm_multiply_add_no() \
1601- mips_emit_mflo(arm_to_mips_reg[rd]) \
1602-
1603-#define arm_multiply_add_yes() \
1604- mips_emit_mflo(reg_temp); \
1605- mips_emit_addu(arm_to_mips_reg[rd], reg_temp, arm_to_mips_reg[rn]) \
1606-
1607-u32 cycle_multiply(_rs)
1608-{
1609- u32 mult_rs = arm_to_mips_reg[_rs];
1610- if(((s32)mult_rs) < 0)
1611- mult_rs = ~mult_rs;
1612-
1613- if((mult_rs & 0xFFFFFF00) == 0) /* m=1 for Bit 31-8 */
1614- return 1;
1615- else
1616- if((mult_rs & 0xFFFF0000) == 0) /* m=2 for Bit 31-16 */
1617- return 2;
1618- else
1619- if((mult_rs & 0xFF000000) == 0) /* m=3 for Bit 31-24 */
1620- return 3;
1621- else /* m=4 otherwise */
1622- return 4;
1623-}
1624-
1625-/* 1S+mI */
1626-#define cycle_arm_multiply_add_no() \
1627- cycle_count += cycle_multiply(rs) \
1628-
1629-/* 1S+mI+1I */
1630-#define cycle_arm_multiply_add_yes() \
1631- cycle_count += 1 + cycle_multiply(rs) \
1632-
1633-#define arm_multiply(add_op, flags) \
1634-{ \
1635- arm_decode_multiply(); \
1636- cycle_arm_multiply_add_##add_op(); \
1637- mips_emit_multu(arm_to_mips_reg[rm], arm_to_mips_reg[rs]); \
1638- arm_multiply_add_##add_op(); \
1639- arm_multiply_flags_##flags(arm_to_mips_reg[rd]); \
1640-} \
1641-
1642-#define arm_multiply_long_flags_yes(_rdlo, _rdhi) \
1643- mips_emit_sltiu(reg_z_cache, _rdlo, 1); \
1644- mips_emit_sltiu(reg_a0, _rdhi, 1); \
1645- mips_emit_and(reg_z_cache, reg_z_cache, reg_a0); \
1646- mips_emit_srl(reg_n_cache, _rdhi, 31); \
1647-
1648-#define arm_multiply_long_flags_no(_rdlo, _rdhi) \
1649-
1650-#define arm_multiply_long_add_yes(name) \
1651- mips_emit_mtlo(arm_to_mips_reg[rdlo]); \
1652- mips_emit_mthi(arm_to_mips_reg[rdhi]); \
1653- generate_multiply_##name() \
1654-
1655-#define arm_multiply_long_add_no(name) \
1656- generate_multiply_##name() \
1657-
1658-/* 1S+mI+1I */
1659-#define cycle_arm_multiply_long_add_no() \
1660- cycle_count += 1 + cycle_multiply(rs) \
1661-
1662-/* 1S+mI+2I */
1663-#define cycle_arm_multiply_long_add_yes() \
1664- cycle_count += 2 + cycle_multiply(rs) \
1665-
1666-#define arm_multiply_long(name, add_op, flags) \
1667-{ \
1668- arm_decode_multiply_long(); \
1669- cycle_arm_multiply_long_add_##add_op(); \
1670- arm_multiply_long_add_##add_op(name); \
1671- mips_emit_mflo(arm_to_mips_reg[rdlo]); \
1672- mips_emit_mfhi(arm_to_mips_reg[rdhi]); \
1673- arm_multiply_long_flags_##flags(arm_to_mips_reg[rdlo], \
1674- arm_to_mips_reg[rdhi]); \
1675-} \
1676-
1677-#define arm_psr_read(op_type, psr_reg) \
1678- generate_function_call(execute_read_##psr_reg); \
1679- generate_store_reg(reg_rv, rd) \
1680-
1681-u32 execute_store_cpsr_body(u32 _cpsr, u32 store_mask, u32 address)
1682-{
1683- reg[REG_CPSR] = _cpsr;
1684- if(store_mask & 0xFF)
1685- {
1686- set_cpu_mode(cpu_modes[_cpsr & 0x1F]);
1687- if((io_registers[REG_IE] & io_registers[REG_IF]) &&
1688- io_registers[REG_IME] && ((_cpsr & 0x80) == 0))
1689- {
1690- reg_mode[MODE_IRQ][6] = address + 4;
1691- spsr[MODE_IRQ] = _cpsr;
1692- reg[REG_CPSR] = 0xD2;
1693- set_cpu_mode(MODE_IRQ);
1694- return 0x00000018;
1695- }
1696- }
1697-
1698- return 0;
1699-}
1700-
1701-#define arm_psr_load_new_reg() \
1702- generate_load_reg(reg_a0, rm) \
1703-
1704-#define arm_psr_load_new_imm() \
1705- generate_load_imm(reg_a0, imm) \
1706-
1707-#define arm_psr_store(op_type, psr_reg) \
1708- arm_psr_load_new_##op_type(); \
1709- generate_load_imm(reg_a1, psr_masks[psr_field]); \
1710- generate_load_pc(reg_a2, (pc + 4)); \
1711- generate_function_call_swap_delay(execute_store_##psr_reg) \
1712-
1713-#define arm_psr(op_type, transfer_type, psr_reg) \
1714-{ \
1715- arm_decode_psr_##op_type(); \
1716- arm_psr_##transfer_type(op_type, psr_reg); \
1717-} \
1718-
1719-/* LDR: 1S+1N+1I. LDR PC: 2S+2N+1I. STR: 2N. */
1720-#define cycle_arm_access_memory_load_u32() \
1721- cycle_count += 1 + waitstate_cycles_non_seq[1][reg_a0 >> 24]; \
1722- if(rd == reg_pc) \
1723- cycle_count += 2 \
1724-
1725-#define cycle_arm_access_memory_load_u16() \
1726- cycle_count += 1 + waitstate_cycles_non_seq[0][reg_a0 >> 24]; \
1727- if(rd == reg_pc) \
1728- cycle_count += 2 \
1729-
1730-#define cycle_arm_access_memory_load_s16() \
1731- cycle_arm_access_memory_load_u16() \
1732-
1733-#define cycle_arm_access_memory_load_u8() \
1734- cycle_arm_access_memory_load_u16() \
1735-
1736-#define cycle_arm_access_memory_load_s8() \
1737- cycle_arm_access_memory_load_u16() \
1738-
1739-#define cycle_arm_access_memory_store_u32() \
1740- cycle_count += waitstate_cycles_non_seq[1][reg_a0 >> 24] \
1741-
1742-#define cycle_arm_access_memory_store_u16() \
1743- cycle_count += waitstate_cycles_non_seq[0][reg_a0 >> 24] \
1744-
1745-#define cycle_arm_access_memory_store_s16() \
1746- cycle_arm_access_memory_store_u16() \
1747-
1748-#define cycle_arm_access_memory_store_u8() \
1749- cycle_arm_access_memory_store_u16() \
1750-
1751-#define cycle_arm_access_memory_store_s8() \
1752- cycle_arm_access_memory_store_u16() \
1753-
1754-#define arm_access_memory_load(mem_type) \
1755- cycle_arm_access_memory_load_##mem_type(); \
1756- mips_emit_jal(mips_absolute_offset(execute_load_##mem_type)); \
1757- generate_load_pc(reg_a1, (pc + 8)); \
1758- generate_store_reg(reg_rv, rd); \
1759- check_store_reg_pc_no_flags(rd) \
1760-
1761-#define arm_access_memory_store(mem_type) \
1762- cycle_arm_access_memory_store_##mem_type(); \
1763- generate_load_pc(reg_a2, (pc + 4)); \
1764- generate_load_reg_pc(reg_a1, rd, 12); \
1765- generate_function_call_swap_delay(execute_store_##mem_type) \
1766-
1767-#define arm_access_memory_reg_pre_up() \
1768- mips_emit_addu(reg_a0, arm_to_mips_reg[rn], arm_to_mips_reg[rm]) \
1769-
1770-#define arm_access_memory_reg_pre_down() \
1771- mips_emit_subu(reg_a0, arm_to_mips_reg[rn], arm_to_mips_reg[rm]) \
1772-
1773-#define arm_access_memory_reg_pre(adjust_dir) \
1774- check_load_reg_pc(arm_reg_a0, rn, 8); \
1775- arm_access_memory_reg_pre_##adjust_dir() \
1776-
1777-#define arm_access_memory_reg_pre_wb(adjust_dir) \
1778- arm_access_memory_reg_pre(adjust_dir); \
1779- generate_store_reg(reg_a0, rn) \
1780-
1781-#define arm_access_memory_reg_post_up() \
1782- mips_emit_addu(arm_to_mips_reg[rn], arm_to_mips_reg[rn], \
1783- arm_to_mips_reg[rm]) \
1784-
1785-#define arm_access_memory_reg_post_down() \
1786- mips_emit_subu(arm_to_mips_reg[rn], arm_to_mips_reg[rn], \
1787- arm_to_mips_reg[rm]) \
1788-
1789-#define arm_access_memory_reg_post(adjust_dir) \
1790- generate_load_reg(reg_a0, rn); \
1791- arm_access_memory_reg_post_##adjust_dir() \
1792-
1793-#define arm_access_memory_imm_pre_up() \
1794- mips_emit_addiu(reg_a0, arm_to_mips_reg[rn], offset) \
1795-
1796-#define arm_access_memory_imm_pre_down() \
1797- mips_emit_addiu(reg_a0, arm_to_mips_reg[rn], -offset) \
1798-
1799-#define arm_access_memory_imm_pre(adjust_dir) \
1800- check_load_reg_pc(arm_reg_a0, rn, 8); \
1801- arm_access_memory_imm_pre_##adjust_dir() \
1802-
1803-#define arm_access_memory_imm_pre_wb(adjust_dir) \
1804- arm_access_memory_imm_pre(adjust_dir); \
1805- generate_store_reg(reg_a0, rn) \
1806-
1807-#define arm_access_memory_imm_post_up() \
1808- mips_emit_addiu(arm_to_mips_reg[rn], arm_to_mips_reg[rn], offset) \
1809-
1810-#define arm_access_memory_imm_post_down() \
1811- mips_emit_addiu(arm_to_mips_reg[rn], arm_to_mips_reg[rn], -offset) \
1812-
1813-#define arm_access_memory_imm_post(adjust_dir) \
1814- generate_load_reg(reg_a0, rn); \
1815- arm_access_memory_imm_post_##adjust_dir() \
1816-
1817-#define arm_data_trans_reg(adjust_op, adjust_dir) \
1818- arm_decode_data_trans_reg(); \
1819- rm = generate_load_offset_sh(rm); \
1820- arm_access_memory_reg_##adjust_op(adjust_dir) \
1821-
1822-#define arm_data_trans_imm(adjust_op, adjust_dir) \
1823- arm_decode_data_trans_imm(); \
1824- arm_access_memory_imm_##adjust_op(adjust_dir) \
1825-
1826-#define arm_data_trans_half_reg(adjust_op, adjust_dir) \
1827- arm_decode_half_trans_r(); \
1828- arm_access_memory_reg_##adjust_op(adjust_dir) \
1829-
1830-#define arm_data_trans_half_imm(adjust_op, adjust_dir) \
1831- arm_decode_half_trans_of(); \
1832- arm_access_memory_imm_##adjust_op(adjust_dir) \
1833-
1834-#define arm_access_memory(access_type, direction, adjust_op, mem_type, \
1835- offset_type) \
1836-{ \
1837- arm_data_trans_##offset_type(adjust_op, direction); \
1838- arm_access_memory_##access_type(mem_type); \
1839-} \
1840-
1841-#define word_bit_count(word) \
1842- (bit_count[word >> 8] + bit_count[word & 0xFF]) \
1843-
1844-#define sprint_no(access_type, pre_op, post_op, wb) \
1845-
1846-#define sprint_yes(access_type, pre_op, post_op, wb) \
1847- printf("sbit on %s %s %s %s\n", #access_type, #pre_op, #post_op, #wb) \
1848-
1849-/* LDM, nS+1N+1I. LDM PC, (n+1)S+2N+1I. STM (n-1)S+2N. */
1850-#define arm_block_memory_load() \
1851- if(offset) \
1852- cycle_count += waitstate_cycles_seq[1][reg_a0 >> 24]; \
1853- else \
1854- cycle_count += waitstate_cycles_non_seq[1][reg_a0 >> 24]; \
1855- \
1856- generate_function_call_swap_delay(execute_aligned_load32); \
1857- generate_store_reg(reg_rv, i) \
1858-
1859-#define arm_block_memory_store() \
1860- if(offset) \
1861- cycle_count += waitstate_cycles_seq[1][reg_a0 >> 24]; \
1862- else \
1863- cycle_count += waitstate_cycles_non_seq[1][reg_a0 >> 24]; \
1864- \
1865- generate_load_reg_pc(reg_a1, i, 8); \
1866- generate_function_call_swap_delay(execute_aligned_store32) \
1867-
1868-#define arm_block_memory_final_load() \
1869- arm_block_memory_load() \
1870-
1871-#define arm_block_memory_final_store() \
1872- generate_load_pc(reg_a2, (pc + 4)); \
1873- mips_emit_jal(mips_absolute_offset(execute_store_u32)); \
1874- generate_load_reg(reg_a1, i) \
1875-
1876-#define arm_block_memory_adjust_pc_store() \
1877- cycle_count++; \
1878-
1879-#define arm_block_memory_adjust_pc_load() \
1880- cycle_count++; \
1881- if(reg_list & 0x8000) \
1882- { \
1883- cycle_count += 2; \
1884- generate_mov(reg_a0, reg_rv); \
1885- generate_indirect_branch_arm(); \
1886- } \
1887-
1888-#define arm_block_memory_sp_load() \
1889- mips_emit_lw(arm_to_mips_reg[i], reg_a1, offset); \
1890-
1891-#define arm_block_memory_sp_store() \
1892-{ \
1893- u32 store_reg = i; \
1894- check_load_reg_pc(arm_reg_a0, store_reg, 8); \
1895- mips_emit_sw(arm_to_mips_reg[store_reg], reg_a1, offset); \
1896-} \
1897-
1898-#define arm_block_memory_sp_adjust_pc_store() \
1899-
1900-#define arm_block_memory_sp_adjust_pc_load() \
1901- cycle_count++; \
1902- if(reg_list & 0x8000) \
1903- { \
1904- cycle_count += 2; \
1905- generate_indirect_branch_arm(); \
1906- } \
1907-
1908-#define arm_block_memory_offset_down_a() \
1909- mips_emit_addiu(reg_a2, base_reg, (-((word_bit_count(reg_list) * 4) - 4))) \
1910-
1911-#define arm_block_memory_offset_down_b() \
1912- mips_emit_addiu(reg_a2, base_reg, (word_bit_count(reg_list) * -4)) \
1913-
1914-#define arm_block_memory_offset_no() \
1915- mips_emit_addu(reg_a2, base_reg, reg_zero) \
1916-
1917-#define arm_block_memory_offset_up() \
1918- mips_emit_addiu(reg_a2, base_reg, 4) \
1919-
1920-#define arm_block_memory_writeback_down() \
1921- mips_emit_addiu(base_reg, base_reg, (-(word_bit_count(reg_list) * 4))) \
1922-
1923-#define arm_block_memory_writeback_up() \
1924- mips_emit_addiu(base_reg, base_reg, (word_bit_count(reg_list) * 4)) \
1925-
1926-#define arm_block_memory_writeback_no()
1927-
1928-// Only emit writeback if the register is not in the list
1929-
1930-#define arm_block_memory_writeback_load(writeback_type) \
1931- if(!((reg_list >> rn) & 0x01)) \
1932- { \
1933- arm_block_memory_writeback_##writeback_type(); \
1934- } \
1935-
1936-#define arm_block_memory_writeback_store(writeback_type) \
1937- arm_block_memory_writeback_##writeback_type() \
1938-
1939-#define arm_block_memory(access_type, offset_type, writeback_type, s_bit) \
1940-{ \
1941- arm_decode_block_trans(); \
1942- u32 i; \
1943- u32 offset = 0; \
1944- u32 base_reg = arm_to_mips_reg[rn]; \
1945- \
1946- arm_block_memory_offset_##offset_type(); \
1947- arm_block_memory_writeback_##access_type(writeback_type); \
1948- \
1949- if((rn == REG_SP) && iwram_stack_optimize) \
1950- { \
1951- mips_emit_andi(reg_a1, reg_a2, 0x7FFC); \
1952- generate_load_imm(reg_a0, ((u32)(iwram + 0x8000))); \
1953- mips_emit_addu(reg_a1, reg_a1, reg_a0); \
1954- \
1955- for(i = 0; i < 16; i++) \
1956- { \
1957- if((reg_list >> i) & 0x01) \
1958- { \
1959- cycle_count++; \
1960- arm_block_memory_sp_##access_type(); \
1961- offset += 4; \
1962- } \
1963- } \
1964- \
1965- arm_block_memory_sp_adjust_pc_##access_type(); \
1966- } \
1967- else \
1968- { \
1969- mips_emit_ins(reg_a2, reg_zero, 0, 2); \
1970- \
1971- for(i = 0; i < 16; i++) \
1972- { \
1973- if((reg_list >> i) & 0x01) \
1974- { \
1975- mips_emit_addiu(reg_a0, reg_a2, offset); \
1976- if(reg_list & ~((2 << i) - 1)) \
1977- { \
1978- arm_block_memory_##access_type(); \
1979- offset += 4; \
1980- } \
1981- else \
1982- { \
1983- arm_block_memory_final_##access_type(); \
1984- break; \
1985- } \
1986- } \
1987- } \
1988- \
1989- arm_block_memory_adjust_pc_##access_type(); \
1990- } \
1991-} \
1992-
1993-
1994-// This isn't really a correct implementation, may have to fix later.
1995-
1996-#define arm_swap(type) \
1997-{ \
1998- arm_decode_swap(); \
1999- cycle_count += 3; \
2000- mips_emit_jal(mips_absolute_offset(execute_load_##type)); \
2001- generate_load_reg(reg_a0, rn); \
2002- generate_mov(reg_a2, reg_rv); \
2003- generate_load_reg(reg_a0, rn); \
2004- mips_emit_jal(mips_absolute_offset(execute_store_##type)); \
2005- generate_load_reg(reg_a1, rm); \
2006- generate_store_reg(reg_a2, rd); \
2007-} \
2008-
2009-
2010-#define thumb_generate_op_load_yes(_rs) \
2011- generate_load_reg(reg_a1, _rs) \
2012-
2013-#define thumb_generate_op_load_no(_rs) \
2014-
2015-#define thumb_generate_op_reg(name, _rd, _rs, _rn) \
2016- generate_op_##name##_reg(arm_to_mips_reg[_rd], \
2017- arm_to_mips_reg[_rs], arm_to_mips_reg[_rn]) \
2018-
2019-#define thumb_generate_op_imm(name, _rd, _rs, _rn) \
2020- generate_op_##name##_imm(arm_to_mips_reg[_rd], arm_to_mips_reg[_rs]) \
2021-
2022-// Types: add_sub, add_sub_imm, alu_op, imm
2023-// Affects N/Z/C/V flags
2024-
2025-#define thumb_data_proc(type, name, rn_type, _rd, _rs, _rn) \
2026-{ \
2027- thumb_decode_##type(); \
2028- thumb_generate_op_##rn_type(name, _rd, _rs, _rn); \
2029-} \
2030-
2031-#define thumb_data_proc_muls(type, rn_type, _rd, _rs, _rn) \
2032-{ \
2033- thumb_decode_##type(); \
2034- cycle_count += cycle_multiply(_rs); /* 1S+mI */ \
2035- thumb_generate_op_##rn_type(muls, _rd, _rs, _rn); \
2036-} \
2037-
2038-#define thumb_data_proc_test(type, name, rn_type, _rs, _rn) \
2039-{ \
2040- thumb_decode_##type(); \
2041- thumb_generate_op_##rn_type(name, 0, _rs, _rn); \
2042-} \
2043-
2044-#define thumb_data_proc_unary(type, name, rn_type, _rd, _rn) \
2045-{ \
2046- thumb_decode_##type(); \
2047- thumb_generate_op_##rn_type(name, _rd, 0, _rn); \
2048-} \
2049-
2050-#define check_store_reg_pc_thumb(_rd) \
2051- if(_rd == REG_PC) \
2052- { \
2053- generate_indirect_branch_cycle_update(thumb); \
2054- } \
2055-
2056-#define thumb_data_proc_hi(name) \
2057-{ \
2058- thumb_decode_hireg_op(); \
2059- if(rd == reg_pc) \
2060- cycle_count += 2; \
2061- u32 dest_rd = rd; \
2062- check_load_reg_pc(arm_reg_a0, rs, 4); \
2063- check_load_reg_pc(arm_reg_a1, rd, 4); \
2064- generate_op_##name##_reg(arm_to_mips_reg[dest_rd], arm_to_mips_reg[rd], \
2065- arm_to_mips_reg[rs]); \
2066- check_store_reg_pc_thumb(dest_rd); \
2067-} \
2068-
2069-/*
2070-
2071-#define thumb_data_proc_hi(name) \
2072-{ \
2073- thumb_decode_hireg_op(); \
2074- check_load_reg_pc(arm_reg_a0, rs, 4); \
2075- check_load_reg_pc(arm_reg_a1, rd, 4); \
2076- generate_op_##name##_reg(arm_to_mips_reg[rd], arm_to_mips_reg[rd], \
2077- arm_to_mips_reg[rs]); \
2078- check_store_reg_pc_thumb(rd); \
2079-} \
2080-
2081-*/
2082-
2083-#define thumb_data_proc_test_hi(name) \
2084-{ \
2085- thumb_decode_hireg_op(); \
2086- check_load_reg_pc(arm_reg_a0, rs, 4); \
2087- check_load_reg_pc(arm_reg_a1, rd, 4); \
2088- generate_op_##name##_reg(reg_temp, arm_to_mips_reg[rd], \
2089- arm_to_mips_reg[rs]); \
2090-} \
2091-
2092-#define thumb_data_proc_mov_hi() \
2093-{ \
2094- thumb_decode_hireg_op(); \
2095- if(rd == reg_pc) \
2096- cycle_count += 2; \
2097- check_load_reg_pc(arm_reg_a0, rs, 4); \
2098- mips_emit_addu(arm_to_mips_reg[rd], arm_to_mips_reg[rs], reg_zero); \
2099- check_store_reg_pc_thumb(rd); \
2100-} \
2101-
2102-#define thumb_load_pc(_rd) \
2103-{ \
2104- thumb_decode_imm(); \
2105- generate_load_pc(arm_to_mips_reg[_rd], (((pc & ~2) + 4) + (imm * 4))); \
2106-} \
2107-
2108-#define thumb_load_sp(_rd) \
2109-{ \
2110- thumb_decode_imm(); \
2111- mips_emit_addiu(arm_to_mips_reg[_rd], reg_r13, (imm * 4)); \
2112-} \
2113-
2114-#define thumb_adjust_sp(value) \
2115-{ \
2116- thumb_decode_add_sp(); \
2117- mips_emit_addiu(reg_r13, reg_r13, (value)); \
2118-} \
2119-
2120-// Decode types: shift, alu_op
2121-// Operation types: lsl, lsr, asr, ror
2122-// Affects N/Z/C flags
2123-
2124-#define thumb_generate_shift_imm(name) \
2125- if(check_generate_c_flag) \
2126- { \
2127- generate_shift_imm_##name##_flags(rd, rs, imm); \
2128- } \
2129- else \
2130- { \
2131- generate_shift_imm_##name##_no_flags(rd, rs, imm); \
2132- } \
2133- if(rs != rd) \
2134- { \
2135- mips_emit_addu(arm_to_mips_reg[rd], arm_to_mips_reg[rs], reg_zero); \
2136- } \
2137-
2138-#define thumb_generate_shift_reg(name) \
2139-{ \
2140- u32 original_rd = rd; \
2141- if(check_generate_c_flag) \
2142- { \
2143- generate_shift_reg_##name##_flags(rd, rs); \
2144- } \
2145- else \
2146- { \
2147- generate_shift_reg_##name##_no_flags(rd, rs); \
2148- } \
2149- mips_emit_addu(arm_to_mips_reg[original_rd], reg_a0, reg_zero); \
2150-} \
2151-
2152-#define cycle_thumb_shift_shift() \
2153-
2154-/* ALU operations LSL,LSR,ASR,ROR 1S+1I */
2155-#define cycle_thumb_shift_alu_op() \
2156- cycle_count++ \
2157-
2158-#define thumb_shift(decode_type, op_type, value_type) \
2159-{ \
2160- cycle_thumb_shift_##decode_type(); \
2161- thumb_decode_##decode_type(); \
2162- thumb_generate_shift_##value_type(op_type); \
2163- generate_op_logic_flags(arm_to_mips_reg[rd]); \
2164-} \
2165-
2166-// Operation types: imm, mem_reg, mem_imm
2167-
2168-/* LDR 1S+1N+1I, STR 2N */
2169-#define cycle_thumb_access_memory_load_u32() \
2170- cycle_count += 1 + waitstate_cycles_non_seq[1][reg_a0 >> 24] \
2171-
2172-#define cycle_thumb_access_memory_load_u16() \
2173- cycle_count += 1 + waitstate_cycles_non_seq[0][reg_a0 >> 24] \
2174-
2175-#define cycle_thumb_access_memory_load_s16() \
2176- cycle_thumb_access_memory_load_u16() \
2177-
2178-#define cycle_thumb_access_memory_load_u8() \
2179- cycle_thumb_access_memory_load_u16() \
2180-
2181-#define cycle_thumb_access_memory_load_s8() \
2182- cycle_thumb_access_memory_load_u16() \
2183-
2184-#define cycle_thumb_access_memory_store_u32() \
2185- cycle_count += waitstate_cycles_non_seq[1][reg_a0 >> 24] \
2186-
2187-#define cycle_thumb_access_memory_store_u16() \
2188- cycle_count += waitstate_cycles_non_seq[0][reg_a0 >> 24] \
2189-
2190-#define cycle_thumb_access_memory_store_s16() \
2191- cycle_thumb_access_memory_store_u16() \
2192-
2193-#define cycle_thumb_access_memory_store_u8() \
2194- cycle_thumb_access_memory_store_u16() \
2195-
2196-#define cycle_thumb_access_memory_store_s8() \
2197- cycle_thumb_access_memory_store_u16() \
2198-
2199-#define thumb_access_memory_load(mem_type, reg_rd) \
2200- cycle_thumb_access_memory_load_##mem_type(); \
2201- mips_emit_jal(mips_absolute_offset(execute_load_##mem_type)); \
2202- generate_load_pc(reg_a1, (pc + 4)); \
2203- generate_store_reg(reg_rv, reg_rd) \
2204-
2205-#define thumb_access_memory_store(mem_type, reg_rd) \
2206- cycle_thumb_access_memory_store_##mem_type(); \
2207- generate_load_pc(reg_a2, (pc + 2)); \
2208- mips_emit_jal(mips_absolute_offset(execute_store_##mem_type)); \
2209- generate_load_reg(reg_a1, reg_rd) \
2210-
2211-#define thumb_access_memory_generate_address_pc_relative(offset, reg_rb, \
2212- reg_ro) \
2213- generate_load_pc(reg_a0, (offset)) \
2214-
2215-#define thumb_access_memory_generate_address_reg_imm(offset, reg_rb, reg_ro) \
2216- mips_emit_addiu(reg_a0, arm_to_mips_reg[reg_rb], (offset)) \
2217-
2218-#define thumb_access_memory_generate_address_reg_imm_sp(offset, reg_rb, reg_ro)\
2219- mips_emit_addiu(reg_a0, arm_to_mips_reg[reg_rb], (offset * 4)) \
2220-
2221-#define thumb_access_memory_generate_address_reg_reg(offset, reg_rb, reg_ro) \
2222- mips_emit_addu(reg_a0, arm_to_mips_reg[reg_rb], arm_to_mips_reg[reg_ro]) \
2223-
2224-#define thumb_access_memory(access_type, op_type, reg_rd, reg_rb, reg_ro, \
2225- address_type, offset, mem_type) \
2226-{ \
2227- thumb_decode_##op_type(); \
2228- thumb_access_memory_generate_address_##address_type(offset, reg_rb, \
2229- reg_ro); \
2230- thumb_access_memory_##access_type(mem_type, reg_rd); \
2231-} \
2232-
2233-
2234-#define thumb_block_address_preadjust_no(base_reg) \
2235- mips_emit_addu(reg_a2, arm_to_mips_reg[base_reg], reg_zero) \
2236-
2237-#define thumb_block_address_preadjust_up(base_reg) \
2238- mips_emit_addiu(reg_a2, arm_to_mips_reg[base_reg], \
2239- (bit_count[reg_list] * 4)); \
2240- mips_emit_addu(arm_to_mips_reg[base_reg], reg_a2, reg_zero) \
2241-
2242-#define thumb_block_address_preadjust_down(base_reg) \
2243- mips_emit_addiu(reg_a2, arm_to_mips_reg[base_reg], \
2244- -(bit_count[reg_list] * 4)); \
2245- mips_emit_addu(arm_to_mips_reg[base_reg], reg_a2, reg_zero) \
2246-
2247-#define thumb_block_address_preadjust_push_lr(base_reg) \
2248- mips_emit_addiu(reg_a2, arm_to_mips_reg[base_reg], \
2249- -((bit_count[reg_list] + 1) * 4)); \
2250- mips_emit_addu(arm_to_mips_reg[base_reg], reg_a2, reg_zero) \
2251-
2252-#define thumb_block_address_postadjust_no(base_reg) \
2253-
2254-#define thumb_block_address_postadjust_up(base_reg) \
2255- mips_emit_addiu(arm_to_mips_reg[base_reg], reg_a2, \
2256- (bit_count[reg_list] * 4)) \
2257-
2258-#define thumb_block_address_postadjust_down(base_reg) \
2259- mips_emit_addiu(arm_to_mips_reg[base_reg], reg_a2, \
2260- -(bit_count[reg_list] * 4)) \
2261-
2262-#define thumb_block_address_postadjust_pop_pc(base_reg) \
2263- mips_emit_addiu(arm_to_mips_reg[base_reg], reg_a2, \
2264- ((bit_count[reg_list] * 4) + 4)) \
2265-
2266-#define thumb_block_address_postadjust_push_lr(base_reg) \
2267-
2268-#define thumb_block_memory_load() \
2269- if(offset) \
2270- cycle_count += waitstate_cycles_seq[1][reg_a0 >> 24]; \
2271- else \
2272- cycle_count += waitstate_cycles_non_seq[1][reg_a0 >> 24]; \
2273- \
2274- generate_function_call_swap_delay(execute_aligned_load32); \
2275- generate_store_reg(reg_rv, i) \
2276-
2277-#define thumb_block_memory_store() \
2278- if(offset) \
2279- cycle_count += waitstate_cycles_seq[1][reg_a0 >> 24]; \
2280- else \
2281- cycle_count += waitstate_cycles_non_seq[1][reg_a0 >> 24]; \
2282- \
2283- mips_emit_jal(mips_absolute_offset(execute_aligned_store32)); \
2284- generate_load_reg(reg_a1, i) \
2285-
2286-#define thumb_block_memory_final_load() \
2287- thumb_block_memory_load() \
2288-
2289-#define thumb_block_memory_final_store() \
2290- generate_load_pc(reg_a2, (pc + 2)); \
2291- mips_emit_jal(mips_absolute_offset(execute_store_u32)); \
2292- generate_load_reg(reg_a1, i) \
2293-
2294-#define thumb_block_memory_final_no(access_type) \
2295- thumb_block_memory_final_##access_type() \
2296-
2297-#define thumb_block_memory_final_up(access_type) \
2298- thumb_block_memory_final_##access_type() \
2299-
2300-#define thumb_block_memory_final_down(access_type) \
2301- thumb_block_memory_final_##access_type() \
2302-
2303-#define thumb_block_memory_final_push_lr(access_type) \
2304- thumb_block_memory_##access_type() \
2305-
2306-#define thumb_block_memory_final_pop_pc(access_type) \
2307- thumb_block_memory_##access_type() \
2308-
2309-#define thumb_block_memory_extra_no() \
2310-
2311-#define thumb_block_memory_extra_up() \
2312-
2313-#define thumb_block_memory_extra_down() \
2314-
2315-#define thumb_block_memory_extra_push_lr() \
2316- mips_emit_addiu(reg_a0, reg_a2, (bit_count[reg_list] * 4)); \
2317- mips_emit_jal(mips_absolute_offset(execute_aligned_store32)); \
2318- generate_load_reg(reg_a1, REG_LR) \
2319-
2320-#define thumb_block_memory_extra_pop_pc() \
2321- mips_emit_jal(mips_absolute_offset(execute_aligned_load32)); \
2322- mips_emit_addiu(reg_a0, reg_a2, (bit_count[reg_list] * 4)); \
2323- generate_mov(reg_a0, reg_rv); \
2324- generate_indirect_branch_cycle_update(thumb) \
2325-
2326-#define thumb_block_memory_sp_load() \
2327- mips_emit_lw(arm_to_mips_reg[i], reg_a1, offset) \
2328-
2329-#define thumb_block_memory_sp_store() \
2330- mips_emit_sw(arm_to_mips_reg[i], reg_a1, offset) \
2331-
2332-#define thumb_block_memory_sp_extra_no() \
2333-
2334-#define thumb_block_memory_sp_extra_up() \
2335-
2336-#define thumb_block_memory_sp_extra_down() \
2337-
2338-#define thumb_block_memory_sp_extra_pop_pc() \
2339- mips_emit_lw(reg_a0, reg_a1, (bit_count[reg_list] * 4)); \
2340- generate_indirect_branch_cycle_update(thumb) \
2341-
2342-#define thumb_block_memory_sp_extra_push_lr() \
2343- cycle_count--; \
2344- mips_emit_sw(reg_r14, reg_a1, (bit_count[reg_list] * 4)) \
2345-
2346-#define cycle_thumb_block_memory_load() \
2347- cycle_count++; \
2348- if(reg_list & 0x8000) \
2349- cycle_count += 2 \
2350-
2351-#define cycle_thumb_block_memory_store() \
2352- cycle_count++ \
2353-
2354-#define thumb_block_memory(access_type, pre_op, post_op, base_reg) \
2355-{ \
2356- thumb_decode_rlist(); \
2357- u32 i; \
2358- u32 offset = 0; \
2359- \
2360- thumb_block_address_preadjust_##pre_op(base_reg); \
2361- thumb_block_address_postadjust_##post_op(base_reg); \
2362- \
2363- cycle_thumb_block_memory_##access_type(); \
2364- \
2365- if((base_reg == REG_SP) && iwram_stack_optimize) \
2366- { \
2367- mips_emit_andi(reg_a1, reg_a2, 0x7FFC); \
2368- generate_load_imm(reg_a0, ((u32)(iwram + 0x8000))); \
2369- generate_add(reg_a1, reg_a0); \
2370- \
2371- for(i = 0; i < 8; i++) \
2372- { \
2373- if((reg_list >> i) & 0x01) \
2374- { \
2375- cycle_count++; \
2376- thumb_block_memory_sp_##access_type(); \
2377- offset += 4; \
2378- } \
2379- } \
2380- \
2381- thumb_block_memory_sp_extra_##post_op(); \
2382- } \
2383- else \
2384- { \
2385- mips_emit_ins(reg_a2, reg_zero, 0, 2); \
2386- \
2387- for(i = 0; i < 8; i++) \
2388- { \
2389- if((reg_list >> i) & 0x01) \
2390- { \
2391- mips_emit_addiu(reg_a0, reg_a2, offset); \
2392- if(reg_list & ~((2 << i) - 1)) \
2393- { \
2394- thumb_block_memory_##access_type(); \
2395- offset += 4; \
2396- } \
2397- else \
2398- { \
2399- thumb_block_memory_final_##post_op(access_type); \
2400- break; \
2401- } \
2402- } \
2403- } \
2404- \
2405- thumb_block_memory_extra_##post_op(); \
2406- } \
2407-} \
2408-
2409-#define thumb_conditional_branch(condition) \
2410-{ \
2411- cycle_count +=2; \
2412- condition_check_type condition_check; \
2413- generate_condition_##condition(); \
2414- generate_branch_no_cycle_update( \
2415- block_exits[block_exit_position].branch_source, \
2416- block_exits[block_exit_position].branch_target); \
2417- generate_branch_patch_conditional(backpatch_address, translation_ptr); \
2418- block_exit_position++; \
2419-} \
2420-
2421-#define arm_conditional_block_header() \
2422- generate_condition() \
2423-
2424-#define arm_b() \
2425- cycle_count += 2; \
2426- generate_branch() \
2427-
2428-#define arm_bl() \
2429- cycle_count += 2; \
2430- generate_load_pc(reg_r14, (pc + 4)); \
2431- generate_branch() \
2432-
2433-#define arm_bx() \
2434- cycle_count += 2; \
2435- arm_decode_branchx(); \
2436- generate_load_reg(reg_a0, rn); \
2437- /*generate_load_pc(reg_a2, pc);*/ \
2438- generate_indirect_branch_dual() \
2439-
2440-#define arm_swi() \
2441- if(((opcode >> 16) & 0xFF) > 0x2A) \
2442- break; \
2443- cycle_count += 2; \
2444- generate_swi_hle_handler((opcode >> 16) & 0xFF); \
2445- generate_load_pc(reg_a0, (pc + 4)); \
2446- generate_function_call_swap_delay(execute_swi); \
2447- generate_branch() \
2448-
2449-#define thumb_b() \
2450- cycle_count += 2; \
2451- generate_branch_cycle_update( \
2452- block_exits[block_exit_position].branch_source, \
2453- block_exits[block_exit_position].branch_target); \
2454- block_exit_position++ \
2455-
2456-#define thumb_bl() \
2457- cycle_count += 2; \
2458- generate_load_pc(reg_r14, ((pc + 2) | 0x01)); \
2459- generate_branch_cycle_update( \
2460- block_exits[block_exit_position].branch_source, \
2461- block_exits[block_exit_position].branch_target); \
2462- block_exit_position++ \
2463-
2464-#define thumb_blh() \
2465-{ \
2466- thumb_decode_branch(); \
2467- generate_alu_imm(addiu, addu, reg_a0, reg_r14, (offset * 2)); \
2468- generate_load_pc(reg_r14, ((pc + 2) | 0x01)); \
2469- generate_indirect_branch_cycle_update(thumb); \
2470- break; \
2471-} \
2472-
2473-#define thumb_bx() \
2474-{ \
2475- cycle_count += 2; \
2476- thumb_decode_hireg_op(); \
2477- generate_load_reg_pc(reg_a0, rs, 4); \
2478- /*generate_load_pc(reg_a2, pc);*/ \
2479- generate_indirect_branch_cycle_update(dual); \
2480-} \
2481-
2482-#define thumb_swi() \
2483- if((opcode & 0xFF) > 0x2A) \
2484- break; \
2485- cycle_count += 2; \
2486- generate_swi_hle_handler(opcode & 0xFF); \
2487- generate_load_pc(reg_a0, (pc + 2)); \
2488- generate_function_call_swap_delay(execute_swi); \
2489- generate_branch_cycle_update( \
2490- block_exits[block_exit_position].branch_source, \
2491- block_exits[block_exit_position].branch_target); \
2492- block_exit_position++ \
2493-
2494-u8 swi_hle_handle[256][2] =
2495-{ /* use bios , emu bios */
2496- { 0x0, 0x0 }, // SWI 0: SoftReset
2497- { 0x0, 0x0 }, // SWI 1: RegisterRAMReset
2498- { 0x0, 0x0 }, // SWI 2: Halt
2499- { 0x0, 0x0 }, // SWI 3: Stop/Sleep
2500- { 0x0, 0x0 }, // SWI 4: IntrWait
2501- { 0x0, 0x0 }, // SWI 5: VBlankIntrWait
2502- { 0x1, 0x1 }, // SWI 6: Div
2503- { 0x1, 0x1 }, // SWI 7: DivArm
2504- { 0x0, 0x1 }, // SWI 8: Sqrt
2505- { 0x0, 0x0 }, // SWI 9: ArcTan
2506- { 0x0, 0x0 }, // SWI A: ArcTan2
2507- { 0x0, 0x1 }, // SWI B: CpuSet
2508- { 0x0, 0x1 }, // SWI C: CpuFastSet
2509- { 0x0, 0x0 }, // SWI D: GetBIOSCheckSum
2510- { 0x0, 0x1 }, // SWI E: BgAffineSet
2511- { 0x0, 0x1 }, // SWI F: ObjAffineSet
2512- { 0x0, 0x0 }, // SWI 10: BitUnpack
2513- { 0x0, 0x0 }, // SWI 11: LZ77UnCompWram
2514- { 0x0, 0x0 }, // SWI 12: LZ77UnCompVram
2515- { 0x0, 0x0 }, // SWI 13: HuffUnComp
2516- { 0x0, 0x0 }, // SWI 14: RLUnCompWram
2517- { 0x0, 0x0 }, // SWI 15: RLUnCompVram
2518- { 0x0, 0x0 }, // SWI 16: Diff8bitUnFilterWram
2519- { 0x0, 0x0 }, // SWI 17: Diff8bitUnFilterVram
2520- { 0x0, 0x0 }, // SWI 18: Diff16bitUnFilter
2521- { 0x0, 0x0 }, // SWI 19: SoundBias
2522- { 0x0, 0x0 }, // SWI 1A: SoundDriverInit
2523- { 0x0, 0x0 }, // SWI 1B: SoundDriverMode
2524- { 0x0, 0x0 }, // SWI 1C: SoundDriverMain
2525- { 0x0, 0x0 }, // SWI 1D: SoundDriverVSync
2526- { 0x0, 0x0 }, // SWI 1E: SoundChannelClear
2527- { 0x0, 0x0 }, // SWI 20: SoundWhatever0
2528- { 0x0, 0x0 }, // SWI 21: SoundWhatever1
2529- { 0x0, 0x0 }, // SWI 22: SoundWhatever2
2530- { 0x0, 0x0 }, // SWI 23: SoundWhatever3
2531- { 0x0, 0x0 }, // SWI 24: SoundWhatever4
2532- { 0x0, 0x0 }, // SWI 25: MultiBoot
2533- { 0x0, 0x0 }, // SWI 26: HardReset
2534- { 0x0, 0x0 }, // SWI 27: CustomHalt
2535- { 0x0, 0x0 }, // SWI 28: SoundDriverVSyncOff
2536- { 0x0, 0x0 }, // SWI 29: SoundDriverVSyncOn
2537- { 0x0, 0x0 } // SWI 2A: SoundGetJumpList
2538-};
2539-
2540-#define generate_swi_hle_handler(_swi_number) \
2541-{ \
2542- u32 swi_number = _swi_number; \
2543- if(swi_hle_handle[swi_number][bios_mode]) \
2544- { \
2545- /* Div */ \
2546- if(swi_number == 0x06) \
2547- { \
2548- mips_emit_div(reg_r0, reg_r1); \
2549- mips_emit_mflo(reg_r0); \
2550- mips_emit_mfhi(reg_r1); \
2551- mips_emit_sra(reg_a0, reg_r0, 31); \
2552- mips_emit_xor(reg_r3, reg_r0, reg_a0); \
2553- mips_emit_subu(reg_r3, reg_r3, reg_a0); \
2554- } \
2555- \
2556- /* Divarm */ \
2557- if(swi_number == 0x07) \
2558- { \
2559- mips_emit_addu(reg_r3, reg_r0,reg_zero); \
2560- mips_emit_addu(reg_r0, reg_r1,reg_zero); \
2561- mips_emit_addu(reg_r1, reg_r3,reg_zero); \
2562- mips_emit_div(reg_r0, reg_r1); \
2563- mips_emit_mflo(reg_r0); \
2564- mips_emit_mfhi(reg_r1); \
2565- mips_emit_sra(reg_a0, reg_r0, 31); \
2566- mips_emit_xor(reg_r3, reg_r0, reg_a0); \
2567- mips_emit_subu(reg_r3, reg_r3, reg_a0); \
2568- } \
2569- \
2570- /* Sqrt */ \
2571- if(swi_number == 0x08) \
2572- { \
2573- mips_emit_addu(reg_a0, reg_r0, reg_zero); \
2574- generate_function_call(bios_sqrt); \
2575- mips_emit_addu(reg_r0, reg_rv, reg_zero); \
2576- } \
2577- \
2578- /* CpuSet */ \
2579- if(swi_number == 0x0B) \
2580- { \
2581- mips_emit_addu(mips_reg_a0, reg_r0, reg_zero); \
2582- mips_emit_addu(mips_reg_a1, reg_r1, reg_zero); \
2583- mips_emit_addu(mips_reg_a2, reg_r2, reg_zero); \
2584- generate_function_call(bios_cpuset); \
2585- } \
2586- \
2587- /* CpuFastSet */ \
2588- if(swi_number == 0x0C) \
2589- { \
2590- mips_emit_addu(mips_reg_a0, reg_r0, reg_zero); \
2591- mips_emit_addu(mips_reg_a1, reg_r1, reg_zero); \
2592- mips_emit_addu(mips_reg_a2, reg_r2, reg_zero); \
2593- generate_function_call(bios_cpufastset); \
2594- } \
2595- \
2596- /* BgAffineSet */ \
2597- if(swi_number == 0x0E) \
2598- { \
2599- mips_emit_addu(mips_reg_a0, reg_r0, reg_zero); \
2600- mips_emit_addu(mips_reg_a1, reg_r1, reg_zero); \
2601- mips_emit_addu(mips_reg_a2, reg_r2, reg_zero); \
2602- generate_function_call(bios_bgaffineset); \
2603- } \
2604- \
2605- /* ObjAffineSet */ \
2606- if(swi_number == 0x0F) \
2607- { \
2608- mips_emit_addu(mips_reg_a0, reg_r0, reg_zero); \
2609- mips_emit_addu(mips_reg_a1, reg_r1, reg_zero); \
2610- mips_emit_addu(mips_reg_a2, reg_r2, reg_zero); \
2611- mips_emit_addu(mips_reg_a3, reg_r3, reg_zero); \
2612- generate_function_call(bios_objaffineset); \
2613- } \
2614- \
2615- break; \
2616- } \
2617-} \
2618-
2619-#define generate_translation_gate(type) \
2620- generate_load_pc(reg_a0, pc); \
2621- generate_indirect_branch_no_cycle_update(type) \
2622-
2623-#define generate_update_pc_reg() \
2624- generate_load_pc(reg_a0, pc); \
2625- mips_emit_sw(reg_a0, reg_base, (REG_PC * 4)) \
2626-
2627-#endif
--- trunk/gpsp-kai-test/src/mips_emit__.h (revision 404)
+++ trunk/gpsp-kai-test/src/mips_emit__.h (nonexistent)
@@ -1,2600 +0,0 @@
1-/* unofficial gameplaySP kai
2- *
3- * Copyright (C) 2006 Exophase <exophase@gmail.com>
4- * Copyright (C) 2007 takka <takka@tfact.net>
5- * Copyright (C) 2007 ????? <?????>
6- *
7- * This program is free software; you can redistribute it and/or
8- * modify it under the terms of the GNU General Public License as
9- * published by the Free Software Foundation; either version 2 of
10- * the License, or (at your option) any later version.
11- *
12- * This program is distributed in the hope that it will be useful,
13- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15- * General Public License for more details.
16- *
17- * You should have received a copy of the GNU General Public License
18- * along with this program; if not, write to the Free Software
19- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20- */
21-
22-#ifndef MIPS_EMIT_H
23-#define MIPS_EMIT_H
24-
25-u32 mips_update_gba(u32 pc);
26-
27-// Although these are defined as a function, don't call them as
28-// such (jump to it instead)
29-void mips_indirect_branch_arm(u32 address);
30-void mips_indirect_branch_thumb(u32 address);
31-void mips_indirect_branch_dual(u32 address);
32-
33-u32 execute_read_cpsr();
34-u32 execute_read_spsr();
35-void execute_swi(u32 pc);
36-
37-u32 execute_spsr_restore(u32 address);
38-void execute_store_cpsr(u32 new_cpsr, u32 store_mask);
39-void execute_store_spsr(u32 new_spsr, u32 store_mask);
40-
41-u32 execute_spsr_restore_body(u32 address);
42-u32 execute_store_cpsr_body(u32 _cpsr, u32 store_mask, u32 address);
43-
44-u32 execute_lsl_flags_reg(u32 value, u32 shift);
45-u32 execute_lsr_flags_reg(u32 value, u32 shift);
46-u32 execute_asr_flags_reg(u32 value, u32 shift);
47-u32 execute_ror_flags_reg(u32 value, u32 shift);
48-
49-void execute_aligned_store32(u32 address, u32 value);
50-u32 execute_aligned_load32(u32 address);
51-
52-void reg_check();
53-
54-typedef enum
55-{
56- mips_reg_zero, // 0
57- mips_reg_at, // 1
58- mips_reg_v0, // 2
59- mips_reg_v1, // 3
60- mips_reg_a0, // 4
61- mips_reg_a1, // 5
62- mips_reg_a2, // 6
63- mips_reg_a3, // 7
64- mips_reg_t0, // 8
65- mips_reg_t1, // 9
66- mips_reg_t2, // 10
67- mips_reg_t3, // 11
68- mips_reg_t4, // 12
69- mips_reg_t5, // 13
70- mips_reg_t6, // 14
71- mips_reg_t7, // 15
72- mips_reg_s0, // 16
73- mips_reg_s1, // 17
74- mips_reg_s2, // 18
75- mips_reg_s3, // 19
76- mips_reg_s4, // 20
77- mips_reg_s5, // 21
78- mips_reg_s6, // 22
79- mips_reg_s7, // 23
80- mips_reg_t8, // 24
81- mips_reg_t9, // 25
82- mips_reg_k0, // 26
83- mips_reg_k1, // 27
84- mips_reg_gp, // 28
85- mips_reg_sp, // 29
86- mips_reg_fp, // 30
87- mips_reg_ra // 31
88-} mips_reg_number;
89-
90-typedef enum
91-{
92- mips_special_sll = 0x00,
93- mips_special_srl = 0x02,
94- mips_special_sra = 0x03,
95- mips_special_sllv = 0x04,
96- mips_special_srlv = 0x06,
97- mips_special_srav = 0x07,
98- mips_special_jr = 0x08,
99- mips_special_jalr = 0x09,
100- mips_special_movz = 0x0A,
101- mips_special_movn = 0x0B,
102- mips_special_mfhi = 0x10,
103- mips_special_mthi = 0x11,
104- mips_special_mflo = 0x12,
105- mips_special_mtlo = 0x13,
106- mips_special_mult = 0x18,
107- mips_special_multu = 0x19,
108- mips_special_div = 0x1A,
109- mips_special_divu = 0x1B,
110- mips_special_madd = 0x1C,
111- mips_special_maddu = 0x1D,
112- mips_special_add = 0x20,
113- mips_special_addu = 0x21,
114- mips_special_sub = 0x22,
115- mips_special_subu = 0x23,
116- mips_special_and = 0x24,
117- mips_special_or = 0x25,
118- mips_special_xor = 0x26,
119- mips_special_nor = 0x27,
120- mips_special_slt = 0x2A,
121- mips_special_sltu = 0x2B
122-} mips_function_special;
123-
124-typedef enum
125-{
126- mips_special3_ext = 0x00,
127- mips_special3_ins = 0x04,
128- mips_special3_bshfl = 0x20
129-} mips_function_special3;
130-
131-typedef enum
132-{
133- mips_regimm_bltz = 0x00,
134- mips_regimm_bltzal = 0x10
135-} mips_function_regimm;
136-
137-typedef enum
138-{
139- mips_opcode_special = 0x00,
140- mips_opcode_regimm = 0x01,
141- mips_opcode_j = 0x02,
142- mips_opcode_jal = 0x03,
143- mips_opcode_beq = 0x04,
144- mips_opcode_bne = 0x05,
145- mips_opcode_blez = 0x06,
146- mips_opcode_bgtz = 0x07,
147- mips_opcode_addi = 0x08,
148- mips_opcode_addiu = 0x09,
149- mips_opcode_slti = 0x0A,
150- mips_opcode_sltiu = 0x0B,
151- mips_opcode_andi = 0x0C,
152- mips_opcode_ori = 0x0D,
153- mips_opcode_xori = 0x0E,
154- mips_opcode_lui = 0x0F,
155- mips_opcode_llo = 0x18,
156- mips_opcode_lhi = 0x19,
157- mips_opcode_trap = 0x1A,
158- mips_opcode_special2 = 0x1C,
159- mips_opcode_special3 = 0x1F,
160- mips_opcode_lb = 0x20,
161- mips_opcode_lh = 0x21,
162- mips_opcode_lw = 0x23,
163- mips_opcode_lbu = 0x24,
164- mips_opcode_lhu = 0x25,
165- mips_opcode_sb = 0x28,
166- mips_opcode_sh = 0x29,
167- mips_opcode_sw = 0x2B,
168-} mips_opcode;
169-
170-#define mips_emit_reg(opcode, rs, rt, rd, shift, function) \
171- *((u32 *)translation_ptr) = (mips_opcode_##opcode << 26) | \
172- (rs << 21) | (rt << 16) | (rd << 11) | (shift << 6) | function; \
173- translation_ptr += 4 \
174-
175-#define mips_emit_special(function, rs, rt, rd, shift) \
176- *((u32 *)translation_ptr) = (mips_opcode_special << 26) | \
177- (rs << 21) | (rt << 16) | (rd << 11) | (shift << 6) | \
178- mips_special_##function; \
179- translation_ptr += 4 \
180-
181-#define mips_emit_special3(function, rs, rt, imm_a, imm_b) \
182- *((u32 *)translation_ptr) = (mips_opcode_special3 << 26) | \
183- (rs << 21) | (rt << 16) | (imm_a << 11) | (imm_b << 6) | \
184- mips_special3_##function; \
185- translation_ptr += 4 \
186-
187-#define mips_emit_imm(opcode, rs, rt, immediate) \
188- *((u32 *)translation_ptr) = (mips_opcode_##opcode << 26) | \
189- (rs << 21) | (rt << 16) | (immediate & 0xFFFF); \
190- translation_ptr += 4 \
191-
192-#define mips_emit_regimm(function, rs, immediate) \
193- *((u32 *)translation_ptr) = (mips_opcode_regimm << 26) | \
194- (rs << 21) | (mips_regimm_##function << 16) | (immediate & 0xFFFF); \
195- translation_ptr += 4 \
196-
197-#define mips_emit_jump(opcode, offset) \
198- *((u32 *)translation_ptr) = (mips_opcode_##opcode << 26) | \
199- (offset & 0x3FFFFFF); \
200- translation_ptr += 4 \
201-
202-#define mips_relative_offset(source, offset) \
203- (((u32)offset - ((u32)source + 4)) / 4) \
204-
205-#define mips_absolute_offset(offset) \
206- ((u32)offset / 4) \
207-
208-// ADDU rd, rs, rt
209-#define mips_emit_addu(rd, rs, rt) \
210- mips_emit_special(addu, rs, rt, rd, 0) \
211-
212-#define mips_emit_subu(rd, rs, rt) \
213- mips_emit_special(subu, rs, rt, rd, 0) \
214-
215-#define mips_emit_xor(rd, rs, rt) \
216- mips_emit_special(xor, rs, rt, rd, 0) \
217-
218-#define mips_emit_add(rd, rs, rt) \
219- mips_emit_special(add, rs, rt, rd, 0) \
220-
221-#define mips_emit_sub(rd, rs, rt) \
222- mips_emit_special(sub, rs, rt, rd, 0) \
223-
224-#define mips_emit_and(rd, rs, rt) \
225- mips_emit_special(and, rs, rt, rd, 0) \
226-
227-#define mips_emit_or(rd, rs, rt) \
228- mips_emit_special(or, rs, rt, rd, 0) \
229-
230-#define mips_emit_nor(rd, rs, rt) \
231- mips_emit_special(nor, rs, rt, rd, 0) \
232-
233-#define mips_emit_slt(rd, rs, rt) \
234- mips_emit_special(slt, rs, rt, rd, 0) \
235-
236-#define mips_emit_sltu(rd, rs, rt) \
237- mips_emit_special(sltu, rs, rt, rd, 0) \
238-
239-#define mips_emit_sllv(rd, rt, rs) \
240- mips_emit_special(sllv, rs, rt, rd, 0) \
241-
242-#define mips_emit_srlv(rd, rt, rs) \
243- mips_emit_special(srlv, rs, rt, rd, 0) \
244-
245-#define mips_emit_srav(rd, rt, rs) \
246- mips_emit_special(srav, rs, rt, rd, 0) \
247-
248-#define mips_emit_rotrv(rd, rt, rs) \
249- mips_emit_special(srlv, rs, rt, rd, 1) \
250-
251-#define mips_emit_sll(rd, rt, shift) \
252- mips_emit_special(sll, 0, rt, rd, shift) \
253-
254-#define mips_emit_srl(rd, rt, shift) \
255- mips_emit_special(srl, 0, rt, rd, shift) \
256-
257-#define mips_emit_sra(rd, rt, shift) \
258- mips_emit_special(sra, 0, rt, rd, shift) \
259-
260-#define mips_emit_rotr(rd, rt, shift) \
261- mips_emit_special(srl, 1, rt, rd, shift) \
262-
263-#define mips_emit_mfhi(rd) \
264- mips_emit_special(mfhi, 0, 0, rd, 0) \
265-
266-#define mips_emit_mflo(rd) \
267- mips_emit_special(mflo, 0, 0, rd, 0) \
268-
269-#define mips_emit_mthi(rs) \
270- mips_emit_special(mthi, rs, 0, 0, 0) \
271-
272-#define mips_emit_mtlo(rs) \
273- mips_emit_special(mtlo, rs, 0, 0, 0) \
274-
275-#define mips_emit_mult(rs, rt) \
276- mips_emit_special(mult, rs, rt, 0, 0) \
277-
278-#define mips_emit_multu(rs, rt) \
279- mips_emit_special(multu, rs, rt, 0, 0) \
280-
281-#define mips_emit_div(rs, rt) \
282- mips_emit_special(div, rs, rt, 0, 0) \
283-
284-#define mips_emit_divu(rs, rt) \
285- mips_emit_special(divu, rs, rt, 0, 0) \
286-
287-#define mips_emit_madd(rs, rt) \
288- mips_emit_special(madd, rs, rt, 0, 0) \
289-
290-#define mips_emit_maddu(rs, rt) \
291- mips_emit_special(maddu, rs, rt, 0, 0) \
292-
293-#define mips_emit_movn(rd, rs, rt) \
294- mips_emit_special(movn, rs, rt, rd, 0) \
295-
296-#define mips_emit_movz(rd, rs, rt) \
297- mips_emit_special(movz, rs, rt, rd, 0) \
298-
299-#define mips_emit_lb(rt, rs, offset) \
300- mips_emit_imm(lb, rs, rt, offset) \
301-
302-#define mips_emit_lbu(rt, rs, offset) \
303- mips_emit_imm(lbu, rs, rt, offset) \
304-
305-#define mips_emit_lh(rt, rs, offset) \
306- mips_emit_imm(lh, rs, rt, offset) \
307-
308-#define mips_emit_lhu(rt, rs, offset) \
309- mips_emit_imm(lhu, rs, rt, offset) \
310-
311-#define mips_emit_lw(rt, rs, offset) \
312- mips_emit_imm(lw, rs, rt, offset) \
313-
314-#define mips_emit_sb(rt, rs, offset) \
315- mips_emit_imm(sb, rs, rt, offset) \
316-
317-#define mips_emit_sh(rt, rs, offset) \
318- mips_emit_imm(sh, rs, rt, offset) \
319-
320-#define mips_emit_sw(rt, rs, offset) \
321- mips_emit_imm(sw, rs, rt, offset) \
322-
323-#define mips_emit_lui(rt, imm) \
324- mips_emit_imm(lui, 0, rt, imm) \
325-
326-#define mips_emit_addiu(rt, rs, imm) \
327- mips_emit_imm(addiu, rs, rt, imm) \
328-
329-#define mips_emit_xori(rt, rs, imm) \
330- mips_emit_imm(xori, rs, rt, imm) \
331-
332-#define mips_emit_ori(rt, rs, imm) \
333- mips_emit_imm(ori, rs, rt, imm) \
334-
335-#define mips_emit_andi(rt, rs, imm) \
336- mips_emit_imm(andi, rs, rt, imm) \
337-
338-#define mips_emit_slti(rt, rs, imm) \
339- mips_emit_imm(slti, rs, rt, imm) \
340-
341-#define mips_emit_sltiu(rt, rs, imm) \
342- mips_emit_imm(sltiu, rs, rt, imm) \
343-
344-#define mips_emit_ext(rt, rs, pos, size) \
345- mips_emit_special3(ext, rs, rt, (size - 1), pos) \
346-
347-#define mips_emit_ins(rt, rs, pos, size) \
348- mips_emit_special3(ins, rs, rt, (pos + size - 1), pos) \
349-
350-// Breaks down if the backpatch offset is greater than 16bits, take care
351-// when using (should be okay if limited to conditional instructions)
352-
353-#define mips_emit_b_filler(type, rs, rt, writeback_location) \
354- (writeback_location) = translation_ptr; \
355- mips_emit_imm(type, rs, rt, 0) \
356-
357-// The backpatch code for this has to be handled differently than the above
358-
359-#define mips_emit_j_filler(writeback_location) \
360- (writeback_location) = translation_ptr; \
361- mips_emit_jump(j, 0) \
362-
363-#define mips_emit_b(type, rs, rt, offset) \
364- mips_emit_imm(type, rs, rt, offset) \
365-
366-#define mips_emit_j(offset) \
367- mips_emit_jump(j, offset) \
368-
369-#define mips_emit_jal(offset) \
370- mips_emit_jump(jal, offset) \
371-
372-#define mips_emit_jr(rs) \
373- mips_emit_special(jr, rs, 0, 0, 0) \
374-
375-#define mips_emit_bltzal(rs, offset) \
376- mips_emit_regimm(bltzal, rs, offset) \
377-
378-#define mips_emit_nop() \
379- mips_emit_sll(reg_zero, reg_zero, 0) \
380-
381-#define reg_base mips_reg_s0
382-#define reg_cycles mips_reg_s1
383-#define reg_a0 mips_reg_a0
384-#define reg_a1 mips_reg_a1
385-#define reg_a2 mips_reg_a2
386-#define reg_rv mips_reg_v0
387-#define reg_pc mips_reg_s3
388-#define reg_temp mips_reg_at
389-#define reg_zero mips_reg_zero
390-
391-#define reg_n_cache mips_reg_s4
392-#define reg_z_cache mips_reg_s5
393-#define reg_c_cache mips_reg_s6
394-#define reg_v_cache mips_reg_s7
395-
396-#define reg_r0 mips_reg_v1
397-#define reg_r1 mips_reg_a3
398-#define reg_r2 mips_reg_t0
399-#define reg_r3 mips_reg_t1
400-#define reg_r4 mips_reg_t2
401-#define reg_r5 mips_reg_t3
402-#define reg_r6 mips_reg_t4
403-#define reg_r7 mips_reg_t5
404-#define reg_r8 mips_reg_t6
405-#define reg_r9 mips_reg_t7
406-#define reg_r10 mips_reg_s2
407-#define reg_r11 mips_reg_t8
408-#define reg_r12 mips_reg_t9
409-#define reg_r13 mips_reg_gp
410-#define reg_r14 mips_reg_fp
411-
412-// Writing to r15 goes straight to a0, to be chained with other ops
413-
414-u32 arm_to_mips_reg[] =
415-{
416- reg_r0,
417- reg_r1,
418- reg_r2,
419- reg_r3,
420- reg_r4,
421- reg_r5,
422- reg_r6,
423- reg_r7,
424- reg_r8,
425- reg_r9,
426- reg_r10,
427- reg_r11,
428- reg_r12,
429- reg_r13,
430- reg_r14,
431- reg_a0,
432- reg_a1,
433- reg_a2,
434- reg_temp
435-};
436-
437-#define arm_reg_a0 15
438-#define arm_reg_a1 16
439-#define arm_reg_a2 17
440-#define arm_reg_temp 18
441-
442-#define generate_load_reg(ireg, reg_index) \
443- mips_emit_addu(ireg, arm_to_mips_reg[reg_index], reg_zero) \
444-
445-#define generate_load_imm(ireg, imm) \
446- if(((s32)imm >= -32768) && ((s32)imm <= 32767)) \
447- { \
448- mips_emit_addiu(ireg, reg_zero, imm); \
449- } \
450- else \
451- { \
452- if(((u32)imm >> 16) == 0x0000) \
453- { \
454- mips_emit_ori(ireg, reg_zero, imm); \
455- } \
456- else \
457- { \
458- mips_emit_lui(ireg, imm >> 16); \
459- \
460- if(((u32)imm & 0x0000FFFF) != 0x00000000) \
461- { \
462- mips_emit_ori(ireg, ireg, imm & 0xFFFF); \
463- } \
464- } \
465- } \
466-
467-#define generate_load_pc(ireg, new_pc) \
468-{ \
469- s32 pc_delta = new_pc - stored_pc; \
470- if((pc_delta >= -32768) && (pc_delta <= 32767)) \
471- { \
472- mips_emit_addiu(ireg, reg_pc, pc_delta); \
473- } \
474- else \
475- { \
476- generate_load_imm(ireg, new_pc); \
477- } \
478-} \
479-
480-#define generate_store_reg(ireg, reg_index) \
481- mips_emit_addu(arm_to_mips_reg[reg_index], ireg, reg_zero) \
482-
483-#define generate_shift_left(ireg, imm) \
484- mips_emit_sll(ireg, ireg, imm) \
485-
486-#define generate_shift_right(ireg, imm) \
487- mips_emit_srl(ireg, ireg, imm) \
488-
489-#define generate_shift_right_arithmetic(ireg, imm) \
490- mips_emit_sra(ireg, ireg, imm) \
491-
492-#define generate_rotate_right(ireg, imm) \
493- mips_emit_rotr(ireg, ireg, imm) \
494-
495-#define generate_add(ireg_dest, ireg_src) \
496- mips_emit_addu(ireg_dest, ireg_dest, ireg_src) \
497-
498-#define generate_sub(ireg_dest, ireg_src) \
499- mips_emit_subu(ireg_dest, ireg_dest, ireg_src) \
500-
501-#define generate_or(ireg_dest, ireg_src) \
502- mips_emit_or(ireg_dest, ireg_dest, ireg_src) \
503-
504-#define generate_xor(ireg_dest, ireg_src) \
505- mips_emit_xor(ireg_dest, ireg_dest, ireg_src) \
506-
507-#define generate_alu_imm(imm_type, reg_type, ireg_dest, ireg_src, imm) \
508- if(((s32)imm >= -32768) && ((s32)imm <= 32767)) \
509- { \
510- mips_emit_##imm_type(ireg_dest, ireg_src, imm); \
511- } \
512- else \
513- { \
514- generate_load_imm(reg_temp, imm); \
515- mips_emit_##reg_type(ireg_dest, ireg_src, reg_temp); \
516- } \
517-
518-#define generate_alu_immu(imm_type, reg_type, ireg_dest, ireg_src, imm) \
519- if(/*((u32)imm >= 0) && */((u32)imm <= 65535)) \
520- { \
521- mips_emit_##imm_type(ireg_dest, ireg_src, imm); \
522- } \
523- else \
524- { \
525- generate_load_imm(reg_temp, imm); \
526- mips_emit_##reg_type(ireg_dest, ireg_src, reg_temp); \
527- } \
528-
529-#define generate_add_imm(ireg, imm) \
530- generate_alu_imm(addiu, add, ireg, ireg, imm) \
531-
532-#define generate_sub_imm(ireg, imm) \
533- generate_alu_imm(addiu, add, ireg, ireg, -imm) \
534-
535-#define generate_xor_imm(ireg, imm) \
536- generate_alu_immu(xori, xor, ireg, ireg, imm) \
537-
538-#define generate_add_reg_reg_imm(ireg_dest, ireg_src, imm) \
539- generate_alu_imm(addiu, add, ireg_dest, ireg_src, imm) \
540-
541-#define generate_and_imm(ireg, imm) \
542- generate_alu_immu(andi, and, ireg, ireg, imm) \
543-
544-#define generate_mov(ireg_dest, ireg_src) \
545- mips_emit_addu(ireg_dest, ireg_src, reg_zero) \
546-
547-#define generate_multiply_s64() \
548- mips_emit_mult(arm_to_mips_reg[rm], arm_to_mips_reg[rs]) \
549-
550-#define generate_multiply_u64() \
551- mips_emit_multu(arm_to_mips_reg[rm], arm_to_mips_reg[rs]) \
552-
553-#define generate_multiply_s64_add() \
554- mips_emit_madd(arm_to_mips_reg[rm], arm_to_mips_reg[rs]) \
555-
556-#define generate_multiply_u64_add() \
557- mips_emit_maddu(arm_to_mips_reg[rm], arm_to_mips_reg[rs]) \
558-
559-#define generate_function_call(function_location) \
560- mips_emit_jal(mips_absolute_offset(function_location)); \
561- mips_emit_nop() \
562-
563-#define generate_function_call_swap_delay(function_location) \
564-{ \
565- u32 delay_instruction = ADDRESS32(translation_ptr, -4); \
566- translation_ptr -= 4; \
567- mips_emit_jal(mips_absolute_offset(function_location)); \
568- ADDRESS32(translation_ptr, 0) = delay_instruction; \
569- translation_ptr += 4; \
570-} \
571-
572-#define generate_swap_delay() \
573-{ \
574- u32 delay_instruction = ADDRESS32(translation_ptr, -8); \
575- u32 branch_instruction = ADDRESS32(translation_ptr, -4); \
576- branch_instruction = (branch_instruction & 0xFFFF0000) | \
577- (((branch_instruction & 0x0000FFFF) + 1) & 0x0000FFFF); \
578- ADDRESS32(translation_ptr, -8) = branch_instruction; \
579- ADDRESS32(translation_ptr, -4) = delay_instruction; \
580-} \
581-
582-#define generate_cycle_update() \
583- if(cycle_count != 0) \
584- { \
585- mips_emit_addiu(reg_cycles, reg_cycles, -cycle_count); \
586- cycle_count = 0; \
587- } \
588-
589-#define generate_cycle_update_force() \
590- mips_emit_addiu(reg_cycles, reg_cycles, -cycle_count); \
591- cycle_count = 0 \
592-
593-#define generate_branch_patch_conditional(dest, offset) \
594- *((u16 *)(dest)) = mips_relative_offset(dest, offset) \
595-
596-#define generate_branch_patch_unconditional(dest, offset) \
597- *((u32 *)(dest)) = (mips_opcode_j << 26) | \
598- ((mips_absolute_offset(offset)) & 0x3FFFFFF) \
599-
600-#define generate_branch_no_cycle_update(writeback_location, new_pc) \
601- { \
602- u8 i; \
603- u8 flag = 0; \
604- for( i = 0; i < idle_loop_targets; i++) \
605- if(pc == idle_loop_target_pc[i]) \
606- flag = 1; \
607- if(flag == 1) \
608- { \
609- generate_load_pc(reg_a0, new_pc); \
610- generate_function_call_swap_delay(mips_update_gba); \
611- mips_emit_j_filler(writeback_location); \
612- mips_emit_nop(); \
613- } \
614- else \
615- { \
616- generate_load_pc(reg_a0, new_pc); \
617- mips_emit_bltzal(reg_cycles, \
618- mips_relative_offset(translation_ptr, update_trampoline)); \
619- generate_swap_delay(); \
620- mips_emit_j_filler(writeback_location); \
621- mips_emit_nop(); \
622- } \
623- } \
624-
625-#define generate_branch_cycle_update(writeback_location, new_pc) \
626- generate_cycle_update(); \
627- generate_branch_no_cycle_update(writeback_location, new_pc) \
628-
629-#define generate_conditional_branch(ireg_a, ireg_b, type, writeback_location) \
630- generate_branch_filler_##type(ireg_a, ireg_b, writeback_location) \
631-
632-// a0 holds the destination
633-
634-#define generate_indirect_branch_cycle_update(type) \
635- mips_emit_j(mips_absolute_offset(mips_indirect_branch_##type)); \
636- generate_cycle_update_force() \
637-
638-#define generate_indirect_branch_no_cycle_update(type) \
639- mips_emit_j(mips_absolute_offset(mips_indirect_branch_##type)); \
640- mips_emit_nop() \
641-
642-#define generate_block_prologue() \
643- update_trampoline = translation_ptr; \
644- __asm__ \
645- ( \
646- "cache 8, 0(%0)\n" \
647- "cache 8, 0(%0)" : : "r"(translation_ptr) \
648- ); \
649- \
650- mips_emit_j(mips_absolute_offset(mips_update_gba)); \
651- mips_emit_nop(); \
652- generate_load_imm(reg_pc, stored_pc) \
653-
654-#define translate_invalidate_dcache() \
655- sceKernelDcacheWritebackAll() \
656-
657-#define block_prologue_size 8
658-
659-#define check_generate_n_flag \
660- (flag_status & 0x08) \
661-
662-#define check_generate_z_flag \
663- (flag_status & 0x04) \
664-
665-#define check_generate_c_flag \
666- (flag_status & 0x02) \
667-
668-#define check_generate_v_flag \
669- (flag_status & 0x01) \
670-
671-#define generate_load_reg_pc(ireg, reg_index, pc_offset) \
672- if(reg_index == REG_PC) \
673- { \
674- generate_load_pc(ireg, (pc + pc_offset)); \
675- } \
676- else \
677- { \
678- generate_load_reg(ireg, reg_index); \
679- } \
680-
681-#define check_load_reg_pc(arm_reg, reg_index, pc_offset) \
682- if(reg_index == REG_PC) \
683- { \
684- reg_index = arm_reg; \
685- generate_load_pc(arm_to_mips_reg[arm_reg], (pc + pc_offset)); \
686- } \
687-
688-#define check_store_reg_pc_no_flags(reg_index) \
689- if(reg_index == REG_PC) \
690- { \
691- generate_indirect_branch_arm(); \
692- } \
693-
694-#define check_store_reg_pc_flags(reg_index) \
695- if(reg_index == REG_PC) \
696- { \
697- generate_function_call(execute_spsr_restore); \
698- generate_indirect_branch_dual(); \
699- } \
700-
701-#define generate_shift_imm_lsl_no_flags(arm_reg, _rm, _shift) \
702- check_load_reg_pc(arm_reg, _rm, 8); \
703- if(_shift != 0) \
704- { \
705- mips_emit_sll(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], _shift); \
706- _rm = arm_reg; \
707- } \
708-
709-#define generate_shift_imm_lsr_no_flags(arm_reg, _rm, _shift) \
710- if(_shift != 0) \
711- { \
712- check_load_reg_pc(arm_reg, _rm, 8); \
713- mips_emit_srl(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], _shift); \
714- } \
715- else \
716- { \
717- mips_emit_addu(arm_to_mips_reg[arm_reg], reg_zero, reg_zero); \
718- } \
719- _rm = arm_reg \
720-
721-#define generate_shift_imm_asr_no_flags(arm_reg, _rm, _shift) \
722- check_load_reg_pc(arm_reg, _rm, 8); \
723- if(_shift != 0) \
724- { \
725- mips_emit_sra(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], _shift); \
726- } \
727- else \
728- { \
729- mips_emit_sra(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], 31); \
730- } \
731- _rm = arm_reg \
732-
733-#define generate_shift_imm_ror_no_flags(arm_reg, _rm, _shift) \
734- check_load_reg_pc(arm_reg, _rm, 8); \
735- if(_shift != 0) \
736- { \
737- mips_emit_rotr(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], _shift); \
738- } \
739- else \
740- { \
741- mips_emit_srl(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], 1); \
742- mips_emit_ins(arm_to_mips_reg[arm_reg], reg_c_cache, 31, 1); \
743- } \
744- _rm = arm_reg \
745-
746-#define generate_shift_imm_lsl_flags(arm_reg, _rm, _shift) \
747- check_load_reg_pc(arm_reg, _rm, 8); \
748- if(_shift != 0) \
749- { \
750- mips_emit_ext(reg_c_cache, arm_to_mips_reg[_rm], (32 - _shift), 1); \
751- mips_emit_sll(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], _shift); \
752- _rm = arm_reg; \
753- } \
754-
755-#define generate_shift_imm_lsr_flags(arm_reg, _rm, _shift) \
756- check_load_reg_pc(arm_reg, _rm, 8); \
757- if(_shift != 0) \
758- { \
759- mips_emit_ext(reg_c_cache, arm_to_mips_reg[_rm], (_shift - 1), 1); \
760- mips_emit_srl(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], _shift); \
761- } \
762- else \
763- { \
764- mips_emit_srl(reg_c_cache, arm_to_mips_reg[_rm], 31); \
765- mips_emit_addu(arm_to_mips_reg[arm_reg], reg_zero, reg_zero); \
766- } \
767- _rm = arm_reg \
768-
769-#define generate_shift_imm_asr_flags(arm_reg, _rm, _shift) \
770- check_load_reg_pc(arm_reg, _rm, 8); \
771- if(_shift != 0) \
772- { \
773- mips_emit_ext(reg_c_cache, arm_to_mips_reg[_rm], (_shift - 1), 1); \
774- mips_emit_sra(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], _shift); \
775- } \
776- else \
777- { \
778- mips_emit_sra(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], 31); \
779- mips_emit_andi(reg_c_cache, arm_to_mips_reg[arm_reg], 1); \
780- } \
781- _rm = arm_reg \
782-
783-#define generate_shift_imm_ror_flags(arm_reg, _rm, _shift) \
784- check_load_reg_pc(arm_reg, _rm, 8); \
785- if(_shift != 0) \
786- { \
787- mips_emit_ext(reg_c_cache, arm_to_mips_reg[_rm], (_shift - 1), 1); \
788- mips_emit_rotr(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], _shift); \
789- } \
790- else \
791- { \
792- mips_emit_andi(reg_temp, arm_to_mips_reg[_rm], 1); \
793- mips_emit_srl(arm_to_mips_reg[arm_reg], arm_to_mips_reg[_rm], 1); \
794- mips_emit_ins(arm_to_mips_reg[arm_reg], reg_c_cache, 31, 1); \
795- mips_emit_addu(reg_c_cache, reg_temp, reg_zero); \
796- } \
797- _rm = arm_reg \
798-
799-#define generate_shift_reg_lsl_no_flags(_rm, _rs) \
800- mips_emit_sltiu(reg_temp, arm_to_mips_reg[_rs], 32); \
801- mips_emit_sllv(reg_a0, arm_to_mips_reg[_rm], arm_to_mips_reg[_rs]); \
802- mips_emit_movz(reg_a0, reg_zero, reg_temp) \
803-
804-#define generate_shift_reg_lsr_no_flags(_rm, _rs) \
805- mips_emit_sltiu(reg_temp, arm_to_mips_reg[_rs], 32); \
806- mips_emit_srlv(reg_a0, arm_to_mips_reg[_rm], arm_to_mips_reg[_rs]); \
807- mips_emit_movz(reg_a0, reg_zero, reg_temp) \
808-
809-#define generate_shift_reg_asr_no_flags(_rm, _rs) \
810- mips_emit_sltiu(reg_temp, arm_to_mips_reg[_rs], 32); \
811- mips_emit_b(bne, reg_temp, reg_zero, 2); \
812- mips_emit_srav(reg_a0, arm_to_mips_reg[_rm], arm_to_mips_reg[_rs]); \
813- mips_emit_sra(reg_a0, reg_a0, 31) \
814-
815-#define generate_shift_reg_ror_no_flags(_rm, _rs) \
816- mips_emit_rotrv(reg_a0, arm_to_mips_reg[_rm], arm_to_mips_reg[_rs]) \
817-
818-#define generate_shift_reg_lsl_flags(_rm, _rs) \
819- generate_load_reg_pc(reg_a0, _rm, 12); \
820- generate_load_reg_pc(reg_a1, _rs, 8); \
821- generate_function_call_swap_delay(execute_lsl_flags_reg) \
822-
823-#define generate_shift_reg_lsr_flags(_rm, _rs) \
824- generate_load_reg_pc(reg_a0, _rm, 12); \
825- generate_load_reg_pc(reg_a1, _rs, 8); \
826- generate_function_call_swap_delay(execute_lsr_flags_reg) \
827-
828-#define generate_shift_reg_asr_flags(_rm, _rs) \
829- generate_load_reg_pc(reg_a0, _rm, 12); \
830- generate_load_reg_pc(reg_a1, _rs, 8); \
831- generate_function_call_swap_delay(execute_asr_flags_reg) \
832-
833-#define generate_shift_reg_ror_flags(_rm, _rs) \
834- mips_emit_b(beq, arm_to_mips_reg[_rs], reg_zero, 3); \
835- mips_emit_addiu(reg_temp, arm_to_mips_reg[_rs], -1); \
836- mips_emit_srlv(reg_temp, arm_to_mips_reg[_rm], reg_temp); \
837- mips_emit_andi(reg_c_cache, reg_temp, 1); \
838- mips_emit_rotrv(reg_a0, arm_to_mips_reg[_rm], arm_to_mips_reg[_rs]) \
839-
840-#define generate_shift_imm(arm_reg, name, flags_op) \
841- u32 shift = (opcode >> 7) & 0x1F; \
842- generate_shift_imm_##name##_##flags_op(arm_reg, rm, shift) \
843-
844-#define generate_shift_reg(arm_reg, name, flags_op) \
845- u32 rs = ((opcode >> 8) & 0x0F); \
846- generate_shift_reg_##name##_##flags_op(rm, rs); \
847- rm = arm_reg \
848-
849-// Made functions due to the macro expansion getting too large.
850-// Returns a new rm if it redirects it (which will happen on most of these
851-// cases)
852-
853-#define generate_load_rm_sh_builder(flags_op) \
854-u32 generate_load_rm_sh_##flags_op(u32 rm) \
855-{ \
856- switch((opcode >> 4) & 0x07) \
857- { \
858- /* LSL imm */ \
859- case 0x0: \
860- { \
861- generate_shift_imm(arm_reg_a0, lsl, flags_op); \
862- break; \
863- } \
864- \
865- /* LSL reg */ \
866- case 0x1: \
867- { \
868- generate_shift_reg(arm_reg_a0, lsl, flags_op); \
869- break; \
870- } \
871- \
872- /* LSR imm */ \
873- case 0x2: \
874- { \
875- generate_shift_imm(arm_reg_a0, lsr, flags_op); \
876- break; \
877- } \
878- \
879- /* LSR reg */ \
880- case 0x3: \
881- { \
882- generate_shift_reg(arm_reg_a0, lsr, flags_op); \
883- break; \
884- } \
885- \
886- /* ASR imm */ \
887- case 0x4: \
888- { \
889- generate_shift_imm(arm_reg_a0, asr, flags_op); \
890- break; \
891- } \
892- \
893- /* ASR reg */ \
894- case 0x5: \
895- { \
896- generate_shift_reg(arm_reg_a0, asr, flags_op); \
897- break; \
898- } \
899- \
900- /* ROR imm */ \
901- case 0x6: \
902- { \
903- generate_shift_imm(arm_reg_a0, ror, flags_op); \
904- break; \
905- } \
906- \
907- /* ROR reg */ \
908- case 0x7: \
909- { \
910- generate_shift_reg(arm_reg_a0, ror, flags_op); \
911- break; \
912- } \
913- } \
914- \
915- return rm; \
916-} \
917-
918-#define read_memory_constant_u8(address) \
919- read_memory8(address) \
920-
921-#define read_memory_constant_u16(address) \
922- read_memory16(address) \
923-
924-#define read_memory_constant_u32(address) \
925- read_memory32(address) \
926-
927-#define read_memory_constant_s8(address) \
928- (s8)read_memory8(address) \
929-
930-#define read_memory_constant_s16(address) \
931- (s16)read_memory16_signed(address) \
932-
933-#define generate_load_memory_u8(ireg, offset) \
934- mips_emit_lbu(ireg, ireg, offset) \
935-
936-#define generate_load_memory_u16(ireg, offset) \
937- mips_emit_lhu(ireg, ireg, offset) \
938-
939-#define generate_load_memory_u32(ireg, offset) \
940- mips_emit_lw(ireg, ireg, offset) \
941-
942-#define generate_load_memory_s8(ireg, offset) \
943- mips_emit_lb(ireg, ireg, offset) \
944-
945-#define generate_load_memory_s16(ireg, offset) \
946- mips_emit_lh(ireg, ireg, offset) \
947-
948-#define generate_load_memory(type, ireg, address) \
949-{ \
950- u32 _address = (u32)(address); \
951- u32 _address_hi = (_address + 0x8000) >> 16; \
952- generate_load_imm(ireg, address); \
953- mips_emit_lui(ireg, _address_hi >> 16); \
954- generate_load_memory_##type(ireg, _address - (_address_hi << 16)); \
955-} \
956-
957-#define generate_block_extra_vars() \
958- u32 stored_pc = pc; \
959- u8 *update_trampoline \
960-
961-#define generate_block_extra_vars_arm() \
962- generate_block_extra_vars(); \
963- \
964- auto u32 generate_load_rm_sh_flags(u32 rm); \
965- auto u32 generate_load_rm_sh_no_flags(u32 rm); \
966- auto u32 generate_load_offset_sh(u32 rm); \
967- auto void generate_indirect_branch_arm(); \
968- auto void generate_indirect_branch_dual(); \
969- \
970- generate_load_rm_sh_builder(flags); \
971- generate_load_rm_sh_builder(no_flags); \
972- \
973- u32 generate_load_offset_sh(u32 rm) \
974- { \
975- switch((opcode >> 5) & 0x03) \
976- { \
977- /* LSL imm */ \
978- case 0x0: \
979- { \
980- generate_shift_imm(arm_reg_a1, lsl, no_flags); \
981- break; \
982- } \
983- \
984- /* LSR imm */ \
985- case 0x1: \
986- { \
987- generate_shift_imm(arm_reg_a1, lsr, no_flags); \
988- break; \
989- } \
990- \
991- /* ASR imm */ \
992- case 0x2: \
993- { \
994- generate_shift_imm(arm_reg_a1, asr, no_flags); \
995- break; \
996- } \
997- \
998- /* ROR imm */ \
999- case 0x3: \
1000- { \
1001- generate_shift_imm(arm_reg_a1, ror, no_flags); \
1002- break; \
1003- } \
1004- } \
1005- \
1006- return rm; \
1007- } \
1008- \
1009- void generate_indirect_branch_arm() \
1010- { \
1011- if(condition == 0x0E) \
1012- { \
1013- generate_indirect_branch_cycle_update(arm); \
1014- } \
1015- else \
1016- { \
1017- generate_indirect_branch_no_cycle_update(arm); \
1018- } \
1019- } \
1020- \
1021- void generate_indirect_branch_dual() \
1022- { \
1023- if(condition == 0x0E) \
1024- { \
1025- generate_indirect_branch_cycle_update(dual); \
1026- } \
1027- else \
1028- { \
1029- generate_indirect_branch_no_cycle_update(dual); \
1030- } \
1031- } \
1032-
1033-#define generate_block_extra_vars_thumb() \
1034- generate_block_extra_vars() \
1035-
1036-// It should be okay to still generate result flags, spsr will overwrite them.
1037-// This is pretty infrequent (returning from interrupt handlers, et al) so
1038-// probably not worth optimizing for.
1039-
1040-u32 execute_spsr_restore_body(u32 address)
1041-{
1042- set_cpu_mode(cpu_modes[reg[REG_CPSR] & 0x1F]);
1043- if((io_registers[REG_IE] & io_registers[REG_IF]) &&
1044- (io_registers[REG_IME] & 0x01) && ((reg[REG_CPSR] & 0x80) == 0))
1045- {
1046- reg_mode[MODE_IRQ][6] = address + 4;
1047- spsr[MODE_IRQ] = reg[REG_CPSR];
1048- reg[REG_CPSR] = /*(reg[REG_CPSR] & ~0xFF) |*/ 0xD2;
1049- address = 0x00000018;
1050- set_cpu_mode(MODE_IRQ);
1051- }
1052-
1053- if(reg[REG_CPSR] & 0x20)
1054- address |= 0x01;
1055-
1056- return address;
1057-}
1058-
1059-typedef enum
1060-{
1061- CONDITION_TRUE,
1062- CONDITION_FALSE,
1063- CONDITION_EQUAL,
1064- CONDITION_NOT_EQUAL
1065-} condition_check_type;
1066-
1067-
1068-#define generate_condition_eq() \
1069- mips_emit_b_filler(beq, reg_z_cache, reg_zero, backpatch_address); \
1070- generate_cycle_update_force() \
1071-
1072-#define generate_condition_ne() \
1073- mips_emit_b_filler(bne, reg_z_cache, reg_zero, backpatch_address); \
1074- generate_cycle_update_force() \
1075-
1076-#define generate_condition_cs() \
1077- mips_emit_b_filler(beq, reg_c_cache, reg_zero, backpatch_address); \
1078- generate_cycle_update_force() \
1079-
1080-#define generate_condition_cc() \
1081- mips_emit_b_filler(bne, reg_c_cache, reg_zero, backpatch_address); \
1082- generate_cycle_update_force() \
1083-
1084-#define generate_condition_mi() \
1085- mips_emit_b_filler(beq, reg_n_cache, reg_zero, backpatch_address); \
1086- generate_cycle_update_force() \
1087-
1088-#define generate_condition_pl() \
1089- mips_emit_b_filler(bne, reg_n_cache, reg_zero, backpatch_address); \
1090- generate_cycle_update_force() \
1091-
1092-#define generate_condition_vs() \
1093- mips_emit_b_filler(beq, reg_v_cache, reg_zero, backpatch_address); \
1094- generate_cycle_update_force() \
1095-
1096-#define generate_condition_vc() \
1097- mips_emit_b_filler(bne, reg_v_cache, reg_zero, backpatch_address); \
1098- generate_cycle_update_force() \
1099-
1100-//(C != 1 or Z) != 0 で次の命令へ
1101-#define generate_condition_hi() \
1102- mips_emit_xori(reg_temp, reg_c_cache, 1); /* C != 1 */ \
1103- mips_emit_or(reg_temp, reg_temp, reg_z_cache); \
1104- mips_emit_b_filler(bne, reg_temp, reg_zero, backpatch_address); \
1105- generate_cycle_update_force() \
1106-
1107-// (C != 1 or Z) == 0 で次の命令へ
1108-#define generate_condition_ls() \
1109- mips_emit_xori(reg_temp, reg_c_cache, 1); \
1110- mips_emit_or(reg_temp, reg_temp, reg_z_cache); \
1111- mips_emit_b_filler(beq, reg_temp, reg_zero, backpatch_address); \
1112- generate_cycle_update_force() \
1113-
1114-#define generate_condition_ge() \
1115- mips_emit_b_filler(bne, reg_n_cache, reg_v_cache, backpatch_address); \
1116- generate_cycle_update_force() \
1117-
1118-#define generate_condition_lt() \
1119- mips_emit_b_filler(beq, reg_n_cache, reg_v_cache, backpatch_address); \
1120- generate_cycle_update_force() \
1121-
1122-// (N != V or Z) != 0 で次の命令へ
1123-#define generate_condition_gt() \
1124- mips_emit_xor(reg_temp, reg_n_cache, reg_v_cache); /* N != V */ \
1125- mips_emit_or(reg_temp, reg_temp, reg_z_cache); \
1126- mips_emit_b_filler(bne, reg_temp, reg_zero, backpatch_address); \
1127- generate_cycle_update_force() \
1128-
1129-// (N != V or Z) == 0 で次の命令へ
1130-#define generate_condition_le() \
1131- mips_emit_xor(reg_temp, reg_n_cache, reg_v_cache); /* N != V */ \
1132- mips_emit_or(reg_temp, reg_temp, reg_z_cache); \
1133- mips_emit_b_filler(beq, reg_temp, reg_zero, backpatch_address); \
1134- generate_cycle_update_force() \
1135-
1136-#define generate_condition() \
1137- switch(condition) \
1138- { \
1139- case 0x0: \
1140- generate_condition_eq(); \
1141- break; \
1142- \
1143- case 0x1: \
1144- generate_condition_ne(); \
1145- break; \
1146- \
1147- case 0x2: \
1148- generate_condition_cs(); \
1149- break; \
1150- \
1151- case 0x3: \
1152- generate_condition_cc(); \
1153- break; \
1154- \
1155- case 0x4: \
1156- generate_condition_mi(); \
1157- break; \
1158- \
1159- case 0x5: \
1160- generate_condition_pl(); \
1161- break; \
1162- \
1163- case 0x6: \
1164- generate_condition_vs(); \
1165- break; \
1166- \
1167- case 0x7: \
1168- generate_condition_vc(); \
1169- break; \
1170- \
1171- case 0x8: \
1172- generate_condition_hi(); \
1173- break; \
1174- \
1175- case 0x9: \
1176- generate_condition_ls(); \
1177- break; \
1178- \
1179- case 0xA: \
1180- generate_condition_ge(); \
1181- break; \
1182- \
1183- case 0xB: \
1184- generate_condition_lt(); \
1185- break; \
1186- \
1187- case 0xC: \
1188- generate_condition_gt(); \
1189- break; \
1190- \
1191- case 0xD: \
1192- generate_condition_le(); \
1193- break; \
1194- \
1195- case 0xE: \
1196- break; \
1197- \
1198- case 0xF: \
1199- break; \
1200- } \
1201-
1202-#define generate_branch() \
1203-{ \
1204- if(condition == 0x0E) \
1205- { \
1206- generate_branch_cycle_update( \
1207- block_exits[block_exit_position].branch_source, \
1208- block_exits[block_exit_position].branch_target); \
1209- } \
1210- else \
1211- { \
1212- generate_branch_no_cycle_update( \
1213- block_exits[block_exit_position].branch_source, \
1214- block_exits[block_exit_position].branch_target); \
1215- } \
1216- block_exit_position++; \
1217-} \
1218-
1219-#define generate_op_and_reg(_rd, _rn, _rm) \
1220- mips_emit_and(_rd, _rn, _rm) \
1221-
1222-#define generate_op_orr_reg(_rd, _rn, _rm) \
1223- mips_emit_or(_rd, _rn, _rm) \
1224-
1225-#define generate_op_eor_reg(_rd, _rn, _rm) \
1226- mips_emit_xor(_rd, _rn, _rm) \
1227-
1228-#define generate_op_bic_reg(_rd, _rn, _rm) \
1229- mips_emit_nor(reg_temp, _rm, reg_zero); \
1230- mips_emit_and(_rd, _rn, reg_temp) \
1231-
1232-#define generate_op_sub_reg(_rd, _rn, _rm) \
1233- mips_emit_subu(_rd, _rn, _rm) \
1234-
1235-#define generate_op_rsb_reg(_rd, _rn, _rm) \
1236- mips_emit_subu(_rd, _rm, _rn) \
1237-
1238-#define generate_op_sbc_reg(_rd, _rn, _rm) \
1239- mips_emit_subu(_rd, _rn, _rm); \
1240- mips_emit_xori(reg_temp, reg_c_cache, 1); \
1241- mips_emit_subu(_rd, _rd, reg_temp) \
1242-
1243-#define generate_op_rsc_reg(_rd, _rn, _rm) \
1244- mips_emit_subu(_rd, _rm, _rn); \
1245- mips_emit_xori(reg_temp, reg_c_cache, 1); \
1246- mips_emit_subu(_rd, _rd, reg_temp) \
1247-
1248-#define generate_op_add_reg(_rd, _rn, _rm) \
1249- mips_emit_addu(_rd, _rn, _rm) \
1250-
1251-#define generate_op_adc_reg(_rd, _rn, _rm) \
1252- mips_emit_addu(reg_temp, _rm, reg_c_cache); \
1253- mips_emit_addu(_rd, _rn, reg_temp) \
1254-
1255-#define generate_op_mov_reg(_rd, _rn, _rm) \
1256- mips_emit_addu(_rd, _rm, reg_zero) \
1257-
1258-#define generate_op_mvn_reg(_rd, _rn, _rm) \
1259- mips_emit_nor(_rd, _rm, reg_zero) \
1260-
1261-#define generate_op_imm_wrapper(name, _rd, _rn) \
1262- if(imm != 0) \
1263- { \
1264- generate_load_imm(reg_a0, imm); \
1265- generate_op_##name##_reg(_rd, _rn, reg_a0); \
1266- } \
1267- else \
1268- { \
1269- generate_op_##name##_reg(_rd, _rn, reg_zero); \
1270- } \
1271-
1272-#define generate_op_and_imm(_rd, _rn) \
1273- generate_alu_immu(andi, and, _rd, _rn, imm) \
1274-
1275-#define generate_op_orr_imm(_rd, _rn) \
1276- generate_alu_immu(ori, or, _rd, _rn, imm) \
1277-
1278-#define generate_op_eor_imm(_rd, _rn) \
1279- generate_alu_immu(xori, xor, _rd, _rn, imm) \
1280-
1281-#define generate_op_bic_imm(_rd, _rn) \
1282- generate_alu_immu(andi, and, _rd, _rn, (~imm)) \
1283-
1284-#define generate_op_sub_imm(_rd, _rn) \
1285- generate_alu_imm(addiu, addu, _rd, _rn, (-imm)) \
1286-
1287-#define generate_op_rsb_imm(_rd, _rn) \
1288- if(imm != 0) \
1289- { \
1290- generate_load_imm(reg_temp, imm); \
1291- mips_emit_subu(_rd, reg_temp, _rn); \
1292- } \
1293- else \
1294- { \
1295- mips_emit_subu(_rd, reg_zero, _rn); \
1296- } \
1297-
1298-#define generate_op_sbc_imm(_rd, _rn) \
1299- generate_op_imm_wrapper(sbc, _rd, _rn) \
1300-
1301-#define generate_op_rsc_imm(_rd, _rn) \
1302- generate_op_imm_wrapper(rsc, _rd, _rn) \
1303-
1304-#define generate_op_add_imm(_rd, _rn) \
1305- generate_alu_imm(addiu, addu, _rd, _rn, imm) \
1306-
1307-#define generate_op_adc_imm(_rd, _rn) \
1308- generate_op_imm_wrapper(adc, _rd, _rn) \
1309-
1310-#define generate_op_mov_imm(_rd, _rn) \
1311- generate_load_imm(_rd, imm) \
1312-
1313-#define generate_op_mvn_imm(_rd, _rn) \
1314- generate_load_imm(_rd, (~imm)) \
1315-
1316-#define generate_op_logic_flags(_rd) \
1317- if(check_generate_n_flag) \
1318- { \
1319- mips_emit_srl(reg_n_cache, _rd, 31); \
1320- } \
1321- if(check_generate_z_flag) \
1322- { \
1323- mips_emit_sltiu(reg_z_cache, _rd, 1); /* if(_rd >= 1) reg_z_cache = 0 */ \
1324- } \
1325-
1326-#define generate_op_sub_flags_prologue(_rn, _rm) \
1327- if(check_generate_c_flag) \
1328- { \
1329- mips_emit_sltu(reg_c_cache, _rn, _rm); /* if(_rn >= _rm) reg_c_cache = 0 */\
1330- mips_emit_xori(reg_c_cache, reg_c_cache, 1); /* reg_c_cache ^= 1 */ \
1331- } \
1332- if(check_generate_v_flag) \
1333- { \
1334- mips_emit_nor(reg_v_cache, reg_v_cache, _rn); \
1335- mips_emit_and(reg_v_cache, reg_v_cache, _rm); \
1336- } \
1337-
1338-#define generate_op_sub_flags_epilogue(_rd) \
1339- generate_op_logic_flags(_rd); \
1340- if(check_generate_v_flag) \
1341- { \
1342- mips_emit_and(reg_v_cache, reg_v_cache, _rd); \
1343- mips_emit_srl(reg_n_cache, _rd, 31); \
1344- } \
1345-
1346-#define generate_add_flags_prologue(_rn, _rm) \
1347- if(check_generate_c_flag | check_generate_v_flag) \
1348- { \
1349- mips_emit_addu(reg_c_cache, _rn, reg_zero); \
1350- } \
1351- if(check_generate_v_flag) \
1352- { \
1353- mips_emit_or(reg_v_cache, reg_v_cache, _rm); \
1354- mips_emit_nor(reg_v_cache, reg_v_cache, _rn); \
1355- } \
1356-
1357-#define generate_add_flags_epilogue(_rd) \
1358- generate_op_logic_flags(_rd) \
1359- if(check_generate_v_flag) \
1360- { \
1361- mips_emit_slt(reg_a0, _rd, reg_c_cache); \
1362- mips_emit_xor(reg_v_cache, reg_v_cache, reg_a0); \
1363- } \
1364- if(check_generate_c_flag) \
1365- { \
1366- mips_emit_sltu(reg_c_cache, _rd, reg_c_cache); \
1367- } \
1368-
1369-#define generate_op_ands_reg(_rd, _rn, _rm) \
1370- mips_emit_and(_rd, _rn, _rm); \
1371- generate_op_logic_flags(_rd) \
1372-
1373-#define generate_op_orrs_reg(_rd, _rn, _rm) \
1374- mips_emit_or(_rd, _rn, _rm); \
1375- generate_op_logic_flags(_rd) \
1376-
1377-#define generate_op_eors_reg(_rd, _rn, _rm) \
1378- mips_emit_xor(_rd, _rn, _rm); \
1379- generate_op_logic_flags(_rd) \
1380-
1381-#define generate_op_bics_reg(_rd, _rn, _rm) \
1382- mips_emit_nor(reg_temp, _rm, reg_zero); \
1383- mips_emit_and(_rd, _rn, reg_temp); \
1384- generate_op_logic_flags(_rd) \
1385-
1386-#define generate_op_subs_reg(_rd, _rn, _rm) \
1387- generate_op_sub_flags_prologue(_rn, _rm); \
1388- mips_emit_subu(_rd, _rn, _rm); \
1389- generate_op_sub_flags_epilogue(_rd) \
1390-
1391-#define generate_op_rsbs_reg(_rd, _rn, _rm) \
1392- generate_op_sub_flags_prologue(_rm, _rn); \
1393- mips_emit_subu(_rd, _rm, _rn); \
1394- generate_op_sub_flags_epilogue(_rd) \
1395-
1396-#define generate_op_sbcs_reg(_rd, _rn, _rm) \
1397- mips_emit_xori(reg_temp, reg_c_cache, 1); \
1398- mips_emit_addu(reg_temp, _rm, reg_temp); \
1399- generate_op_sub_flags_prologue(_rn, reg_temp); \
1400- mips_emit_subu(_rd, _rn, reg_temp); \
1401- generate_op_sub_flags_epilogue(_rd) \
1402-
1403-#define generate_op_rscs_reg(_rd, _rn, _rm) \
1404- mips_emit_xori(reg_temp, reg_c_cache, 1); \
1405- mips_emit_addu(reg_temp, _rn, reg_temp); \
1406- generate_op_sub_flags_prologue(_rm, reg_temp); \
1407- mips_emit_subu(_rd, _rm, reg_temp); \
1408- generate_op_sub_flags_epilogue(_rd) \
1409-
1410-#define generate_op_adds_reg(_rd, _rn, _rm) \
1411- generate_add_flags_prologue(_rn, _rm); \
1412- mips_emit_addu(_rd, _rn, _rm); \
1413- generate_add_flags_epilogue(_rd) \
1414-
1415-#define generate_op_adcs_reg(_rd, _rn, _rm) \
1416- mips_emit_addu(reg_temp, _rm, reg_c_cache); \
1417- generate_add_flags_prologue(_rn, reg_temp); \
1418- mips_emit_addu(_rd, _rn, reg_temp); \
1419- generate_add_flags_epilogue(_rd) \
1420-
1421-#define generate_op_movs_reg(_rd, _rn, _rm) \
1422- mips_emit_addu(_rd, _rm, reg_zero); \
1423- generate_op_logic_flags(_rd) \
1424-
1425-#define generate_op_mvns_reg(_rd, _rn, _rm) \
1426- mips_emit_nor(_rd, _rm, reg_zero); \
1427- generate_op_logic_flags(_rd) \
1428-
1429-#define generate_op_neg_reg(_rd, _rn, _rm) \
1430- generate_op_subs_reg(_rd, reg_zero, _rm) \
1431-
1432-#define generate_op_muls_reg(_rd, _rn, _rm) \
1433- mips_emit_multu(_rn, _rm); \
1434- mips_emit_mflo(_rd); \
1435- generate_op_logic_flags(_rd) \
1436-
1437-#define generate_op_cmp_reg(_rd, _rn, _rm) \
1438- generate_op_subs_reg(reg_temp, _rn, _rm) \
1439-
1440-#define generate_op_cmn_reg(_rd, _rn, _rm) \
1441- generate_op_adds_reg(reg_temp, _rn, _rm) \
1442-
1443-#define generate_op_tst_reg(_rd, _rn, _rm) \
1444- generate_op_ands_reg(reg_temp, _rn, _rm) \
1445-
1446-#define generate_op_teq_reg(_rd, _rn, _rm) \
1447- generate_op_eors_reg(reg_temp, _rn, _rm) \
1448-
1449-#define generate_op_ands_imm(_rd, _rn) \
1450- generate_alu_immu(andi, and, _rd, _rn, imm); \
1451- generate_op_logic_flags(_rd) \
1452-
1453-#define generate_op_orrs_imm(_rd, _rn) \
1454- generate_alu_immu(ori, or, _rd, _rn, imm); \
1455- generate_op_logic_flags(_rd) \
1456-
1457-#define generate_op_eors_imm(_rd, _rn) \
1458- generate_alu_immu(xori, xor, _rd, _rn, imm); \
1459- generate_op_logic_flags(_rd) \
1460-
1461-#define generate_op_bics_imm(_rd, _rn) \
1462- generate_alu_immu(andi, and, _rd, _rn, (~imm)); \
1463- generate_op_logic_flags(_rd) \
1464-
1465-#define generate_op_subs_imm(_rd, _rn) \
1466- generate_op_imm_wrapper(subs, _rd, _rn) \
1467-
1468-#define generate_op_rsbs_imm(_rd, _rn) \
1469- generate_op_imm_wrapper(rsbs, _rd, _rn) \
1470-
1471-#define generate_op_sbcs_imm(_rd, _rn) \
1472- generate_op_imm_wrapper(sbcs, _rd, _rn) \
1473-
1474-#define generate_op_rscs_imm(_rd, _rn) \
1475- generate_op_imm_wrapper(rscs, _rd, _rn) \
1476-
1477-#define generate_op_adds_imm(_rd, _rn) \
1478- generate_op_imm_wrapper(adds, _rd, _rn) \
1479-
1480-#define generate_op_adcs_imm(_rd, _rn) \
1481- generate_op_imm_wrapper(adcs, _rd, _rn) \
1482-
1483-#define generate_op_movs_imm(_rd, _rn) \
1484- generate_load_imm(_rd, imm); \
1485- generate_op_logic_flags(_rd) \
1486-
1487-#define generate_op_mvns_imm(_rd, _rn) \
1488- generate_load_imm(_rd, (~imm)); \
1489- generate_op_logic_flags(_rd) \
1490-
1491-#define generate_op_cmp_imm(_rd, _rn) \
1492- generate_op_imm_wrapper(cmp, _rd, _rn) \
1493-
1494-#define generate_op_cmn_imm(_rd, _rn) \
1495- generate_op_imm_wrapper(cmn, _rd, _rn) \
1496-
1497-#define generate_op_tst_imm(_rd, _rn) \
1498- generate_op_ands_imm(reg_temp, _rn) \
1499-
1500-#define generate_op_teq_imm(_rd, _rn) \
1501- generate_op_eors_imm(reg_temp, _rn) \
1502-
1503-#define arm_generate_op_load_yes() \
1504- generate_load_reg_pc(reg_a1, rn, 8) \
1505-
1506-#define arm_generate_op_load_no() \
1507-
1508-#define arm_op_check_yes() \
1509- check_load_reg_pc(arm_reg_a1, rn, 8) \
1510-
1511-#define arm_op_check_no() \
1512-
1513-#define arm_generate_op_reg_flags(name, load_op) \
1514- arm_decode_data_proc_reg(); \
1515- if(check_generate_c_flag) \
1516- { \
1517- rm = generate_load_rm_sh_flags(rm); \
1518- } \
1519- else \
1520- { \
1521- rm = generate_load_rm_sh_no_flags(rm); \
1522- } \
1523- \
1524- arm_op_check_##load_op(); \
1525- generate_op_##name##_reg(arm_to_mips_reg[rd], arm_to_mips_reg[rn], \
1526- arm_to_mips_reg[rm]) \
1527-
1528-#define arm_generate_op_reg(name, load_op) \
1529- arm_decode_data_proc_reg(); \
1530- rm = generate_load_rm_sh_no_flags(rm); \
1531- arm_op_check_##load_op(); \
1532- generate_op_##name##_reg(arm_to_mips_reg[rd], arm_to_mips_reg[rn], \
1533- arm_to_mips_reg[rm]) \
1534-
1535-#define arm_generate_op_imm(name, load_op) \
1536- arm_decode_data_proc_imm(); \
1537- arm_op_check_##load_op(); \
1538- generate_op_##name##_imm(arm_to_mips_reg[rd], arm_to_mips_reg[rn]) \
1539-
1540-#define arm_generate_op_imm_flags(name, load_op) \
1541- arm_generate_op_imm(name, load_op) \
1542-
1543-
1544-#define arm_data_proc(name, type, flags_op) \
1545-{ \
1546- arm_generate_op_##type(name, yes); \
1547- check_store_reg_pc_##flags_op(rd); \
1548-} \
1549-
1550-#define arm_data_proc_test(name, type) \
1551-{ \
1552- arm_generate_op_##type(name, yes); \
1553-} \
1554-
1555-#define arm_data_proc_unary(name, type, flags_op) \
1556-{ \
1557- arm_generate_op_##type(name, no); \
1558- check_store_reg_pc_##flags_op(rd); \
1559-} \
1560-
1561-#define arm_multiply_flags_yes(_rd) \
1562- generate_op_logic_flags(_rd) \
1563-
1564-#define arm_multiply_flags_no(_rd) \
1565-
1566-#define arm_multiply_add_no() \
1567- mips_emit_mflo(arm_to_mips_reg[rd]) \
1568-
1569-#define arm_multiply_add_yes() \
1570- mips_emit_mflo(reg_temp); \
1571- mips_emit_addu(arm_to_mips_reg[rd], reg_temp, arm_to_mips_reg[rn]) \
1572-
1573-#define arm_multiply(add_op, flags) \
1574-{ \
1575- arm_decode_multiply(); \
1576- mips_emit_multu(arm_to_mips_reg[rm], arm_to_mips_reg[rs]); \
1577- arm_multiply_add_##add_op(); \
1578- arm_multiply_flags_##flags(arm_to_mips_reg[rd]); \
1579-} \
1580-
1581-#define arm_multiply_long_flags_yes(_rdlo, _rdhi) \
1582- mips_emit_sltiu(reg_z_cache, _rdlo, 1); \
1583- mips_emit_sltiu(reg_a0, _rdhi, 1); \
1584- mips_emit_and(reg_z_cache, reg_z_cache, reg_a0); \
1585- mips_emit_srl(reg_n_cache, _rdhi, 31); \
1586-
1587-#define arm_multiply_long_flags_no(_rdlo, _rdhi) \
1588-
1589-#define arm_multiply_long_add_yes(name) \
1590- mips_emit_mtlo(arm_to_mips_reg[rdlo]); \
1591- mips_emit_mthi(arm_to_mips_reg[rdhi]); \
1592- generate_multiply_##name() \
1593-
1594-#define arm_multiply_long_add_no(name) \
1595- generate_multiply_##name() \
1596-
1597-#define arm_multiply_long(name, add_op, flags) \
1598-{ \
1599- arm_decode_multiply_long(); \
1600- arm_multiply_long_add_##add_op(name); \
1601- mips_emit_mflo(arm_to_mips_reg[rdlo]); \
1602- mips_emit_mfhi(arm_to_mips_reg[rdhi]); \
1603- arm_multiply_long_flags_##flags(arm_to_mips_reg[rdlo], \
1604- arm_to_mips_reg[rdhi]); \
1605-} \
1606-
1607-#define arm_psr_read(op_type, psr_reg) \
1608- generate_function_call(execute_read_##psr_reg); \
1609- generate_store_reg(reg_rv, rd) \
1610-
1611-u32 execute_store_cpsr_body(u32 _cpsr, u32 store_mask, u32 address)
1612-{
1613- reg[REG_CPSR] = _cpsr;
1614- if(store_mask & 0xFF)
1615- {
1616- set_cpu_mode(cpu_modes[_cpsr & 0x1F]);
1617- if((io_registers[REG_IE] & io_registers[REG_IF]) &&
1618- (io_registers[REG_IME] & 0x01) && ((_cpsr & 0x80) == 0))
1619- {
1620- reg_mode[MODE_IRQ][6] = address + 4;
1621- spsr[MODE_IRQ] = _cpsr;
1622- reg[REG_CPSR] = /*(reg[REG_CPSR] & ~0xFF) |*/ 0xD2;
1623- set_cpu_mode(MODE_IRQ);
1624- return 0x00000018;
1625- }
1626- }
1627-
1628- return 0;
1629-}
1630-
1631-#define arm_psr_load_new_reg() \
1632- generate_load_reg(reg_a0, rm) \
1633-
1634-#define arm_psr_load_new_imm() \
1635- generate_load_imm(reg_a0, imm) \
1636-
1637-#define arm_psr_store(op_type, psr_reg) \
1638- arm_psr_load_new_##op_type(); \
1639- generate_load_imm(reg_a1, psr_masks[psr_field]); \
1640- generate_load_pc(reg_a2, (pc + 4)); \
1641- generate_function_call_swap_delay(execute_store_##psr_r