summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu/arm7/arm7.h
blob: ea1059fdfa3863d8876805118d08a38b7656dbd8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
// license:???
// copyright-holders:???
/*****************************************************************************
 *
 *   arm7.h
 *   Portable ARM7TDMI CPU Emulator
 *
 *   Copyright Steve Ellenoff, all rights reserved.
 *
 *   - This source code is released as freeware for non-commercial purposes.
 *   - You are free to use and redistribute this code in modified or
 *     unmodified form, provided you list me in the credits.
 *   - If you modify this source code, you must add a notice to each modified
 *     source file that it has been changed.  If you're a nice person, you
 *     will clearly mark each change too.  :)
 *   - If you wish to use this for commercial purposes, please contact me at
 *     sellenoff@hotmail.com
 *   - The author of this copywritten work reserves the right to change the
 *     terms of its usage and license at any time, including retroactively
 *   - This entire notice must remain in the source code.
 *
 *  This work is based on:
 *  #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999'
 *  #2) Arm 2/3/6 emulator By Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino (MAME CORE 0.76)
 *
 *****************************************************************************

 This file contains everything related to the arm7 cpu specific implementation.
 Anything related to the arm7 core itself is defined in arm7core.h instead.

 ******************************************************************************/

#pragma once

#ifndef __ARM7_H__
#define __ARM7_H__

#include "cpu/drcfe.h"
#include "cpu/drcuml.h"
#include "cpu/drcumlsh.h"


#define ARM7_MAX_FASTRAM       4
#define ARM7_MAX_HOTSPOTS      16

enum
{
	CPUINFO_INT_ARM7_DRC_OPTIONS = CPUINFO_INT_CPU_SPECIFIC,

	CPUINFO_INT_ARM7_FASTRAM_SELECT,
	CPUINFO_INT_ARM7_FASTRAM_START,
	CPUINFO_INT_ARM7_FASTRAM_END,
	CPUINFO_INT_ARM7_FASTRAM_READONLY,

	CPUINFO_INT_ARM7_HOTSPOT_SELECT,
	CPUINFO_INT_ARM7_HOTSPOT_PC,
	CPUINFO_INT_ARM7_HOTSPOT_OPCODE,
	CPUINFO_INT_ARM7_HOTSPOT_CYCLES,

	CPUINFO_PTR_ARM7_FASTRAM_BASE = CPUINFO_PTR_CPU_SPECIFIC
};

/***************************************************************************
    COMPILER-SPECIFIC OPTIONS
***************************************************************************/

#define ARM7DRC_STRICT_VERIFY      0x0001          /* verify all instructions */
#define ARM7DRC_FLUSH_PC           0x0008          /* flush the PC value before each memory access */

#define ARM7DRC_COMPATIBLE_OPTIONS (ARM7DRC_STRICT_VERIFY | ARM7DRC_FLUSH_PC)
#define ARM7DRC_FASTEST_OPTIONS    (0)

/****************************************************************************************************
 *  PUBLIC FUNCTIONS
 ***************************************************************************************************/

class arm7_cpu_device : public cpu_device
{
public:
	// construction/destruction
	arm7_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
	arm7_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source, UINT8 archRev, UINT8 archFlags, endianness_t endianness = ENDIANNESS_LITTLE);

protected:
	// device-level overrides
	virtual void device_start();
	virtual void device_reset();

	// device_execute_interface overrides
	virtual UINT32 execute_min_cycles() const { return 3; }
	virtual UINT32 execute_max_cycles() const { return 4; }
	virtual UINT32 execute_input_lines() const { return 4; } /* There are actually only 2 input lines: we use 3 variants of the ABORT line while there is only 1 real one */
	virtual void execute_run();
	virtual void execute_set_input(int inputnum, int state);

	// device_memory_interface overrides
	virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return (spacenum == AS_PROGRAM) ? &m_program_config : NULL; }
	virtual bool memory_translate(address_spacenum spacenum, int intention, offs_t &address);

	// device_state_interface overrides
	virtual void state_export(const device_state_entry &entry);
	void state_string_export(const device_state_entry &entry, std::string &str);

	// device_disasm_interface overrides
	virtual UINT32 disasm_min_opcode_bytes() const { return 2; }
	virtual UINT32 disasm_max_opcode_bytes() const { return 4; }
	virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);

	address_space_config m_program_config;

	UINT32 m_r[/*NUM_REGS*/37];
	UINT32 m_pendingIrq;
	UINT32 m_pendingFiq;
	UINT32 m_pendingAbtD;
	UINT32 m_pendingAbtP;
	UINT32 m_pendingUnd;
	UINT32 m_pendingSwi;
	int m_icount;
	endianness_t m_endian;
	address_space *m_program;
	direct_read_data *m_direct;

	/* Coprocessor Registers */
	UINT32 m_control;
	UINT32 m_tlbBase;
	UINT32 m_faultStatus[2];
	UINT32 m_faultAddress;
	UINT32 m_fcsePID;
	UINT32 m_domainAccessControl;

	UINT8 m_archRev;          // ARM architecture revision (3, 4, and 5 are valid)
	UINT8 m_archFlags;        // architecture flags

//#if ARM7_MMU_ENABLE_HACK
//  UINT32 mmu_enable_addr; // workaround for "MMU is enabled when PA != VA" problem
//#endif

	UINT32 m_copro_id;

	// For debugger
	UINT32 m_pc;

	INT64 saturate_qbit_overflow(INT64 res);
	void SwitchMode(UINT32 cpsr_mode_val);
	UINT32 decodeShift(UINT32 insn, UINT32 *pCarry);
	int loadInc(UINT32 pat, UINT32 rbv, UINT32 s, int mode);
	int loadDec(UINT32 pat, UINT32 rbv, UINT32 s, int mode);
	int storeInc(UINT32 pat, UINT32 rbv, int mode);
	int storeDec(UINT32 pat, UINT32 rbv, int mode);
	void HandleCoProcDO(UINT32 insn);
	void HandleCoProcRT(UINT32 insn);
	void HandleCoProcDT(UINT32 insn);
	void HandleBranch(UINT32 insn);
	void HandleMemSingle(UINT32 insn);
	void HandleHalfWordDT(UINT32 insn);
	void HandleSwap(UINT32 insn);
	void HandlePSRTransfer(UINT32 insn);
	void HandleALU(UINT32 insn);
	void HandleMul(UINT32 insn);
	void HandleSMulLong(UINT32 insn);
	void HandleUMulLong(UINT32 insn);
	void HandleMemBlock(UINT32 insn);
	void arm7ops_0123(UINT32 insn);
	void arm7ops_4567(UINT32 insn);
	void arm7ops_89(UINT32 insn);
	void arm7ops_ab(UINT32 insn);
	void arm7ops_cd(UINT32 insn);
	void arm7ops_e(UINT32 insn);
	void arm7ops_f(UINT32 insn);
	void set_cpsr(UINT32 val);
	bool arm7_tlb_translate(offs_t &addr, int flags);
	UINT32 arm7_tlb_get_first_level_descriptor( UINT32 vaddr );
	UINT32 arm7_tlb_get_second_level_descriptor( UINT32 granularity, UINT32 first_desc, UINT32 vaddr );
	int detect_fault(int permission, int ap, int flags);
	void arm7_check_irq_state();
	void arm7_cpu_write32(UINT32 addr, UINT32 data);
	void arm7_cpu_write16(UINT32 addr, UINT16 data);
	void arm7_cpu_write8(UINT32 addr, UINT8 data);
	UINT32 arm7_cpu_read32(UINT32 addr);
	UINT16 arm7_cpu_read16(UINT32 addr);
	UINT8 arm7_cpu_read8(UINT32 addr);

	// Coprocessor support
	DECLARE_WRITE32_MEMBER( arm7_do_callback );
	DECLARE_READ32_MEMBER( arm7_rt_r_callback );
	DECLARE_WRITE32_MEMBER( arm7_rt_w_callback );
	void arm7_dt_r_callback(UINT32 insn, UINT32 *prn);
	void arm7_dt_w_callback(UINT32 insn, UINT32 *prn);

	void tg00_0(UINT32 pc, UINT32 insn);
	void tg00_1(UINT32 pc, UINT32 insn);
	void tg01_0(UINT32 pc, UINT32 insn);
	void tg01_10(UINT32 pc, UINT32 insn);
	void tg01_11(UINT32 pc, UINT32 insn);
	void tg01_12(UINT32 pc, UINT32 insn);
	void tg01_13(UINT32 pc, UINT32 insn);
	void tg02_0(UINT32 pc, UINT32 insn);
	void tg02_1(UINT32 pc, UINT32 insn);
	void tg03_0(UINT32 pc, UINT32 insn);
	void tg03_1(UINT32 pc, UINT32 insn);
	void tg04_00_00(UINT32 pc, UINT32 insn);
	void tg04_00_01(UINT32 pc, UINT32 insn);
	void tg04_00_02(UINT32 pc, UINT32 insn);
	void tg04_00_03(UINT32 pc, UINT32 insn);
	void tg04_00_04(UINT32 pc, UINT32 insn);
	void tg04_00_05(UINT32 pc, UINT32 insn);
	void tg04_00_06(UINT32 pc, UINT32 insn);
	void tg04_00_07(UINT32 pc, UINT32 insn);
	void tg04_00_08(UINT32 pc, UINT32 insn);
	void tg04_00_09(UINT32 pc, UINT32 insn);
	void tg04_00_0a(UINT32 pc, UINT32 insn);
	void tg04_00_0b(UINT32 pc, UINT32 insn);
	void tg04_00_0c(UINT32 pc, UINT32 insn);
	void tg04_00_0d(UINT32 pc, UINT32 insn);
	void tg04_00_0e(UINT32 pc, UINT32 insn);
	void tg04_00_0f(UINT32 pc, UINT32 insn);
	void tg04_01_00(UINT32 pc, UINT32 insn);
	void tg04_01_01(UINT32 pc, UINT32 insn);
	void tg04_01_02(UINT32 pc, UINT32 insn);
	void tg04_01_03(UINT32 pc, UINT32 insn);
	void tg04_01_10(UINT32 pc, UINT32 insn);
	void tg04_01_11(UINT32 pc, UINT32 insn);
	void tg04_01_12(UINT32 pc, UINT32 insn);
	void tg04_01_13(UINT32 pc, UINT32 insn);
	void tg04_01_20(UINT32 pc, UINT32 insn);
	void tg04_01_21(UINT32 pc, UINT32 insn);
	void tg04_01_22(UINT32 pc, UINT32 insn);
	void tg04_01_23(UINT32 pc, UINT32 insn);
	void tg04_01_30(UINT32 pc, UINT32 insn);
	void tg04_01_31(UINT32 pc, UINT32 insn);
	void tg04_01_32(UINT32 pc, UINT32 insn);
	void tg04_01_33(UINT32 pc, UINT32 insn);
	void tg04_0203(UINT32 pc, UINT32 insn);
	void tg05_0(UINT32 pc, UINT32 insn);
	void tg05_1(UINT32 pc, UINT32 insn);
	void tg05_2(UINT32 pc, UINT32 insn);
	void tg05_3(UINT32 pc, UINT32 insn);
	void tg05_4(UINT32 pc, UINT32 insn);
	void tg05_5(UINT32 pc, UINT32 insn);
	void tg05_6(UINT32 pc, UINT32 insn);
	void tg05_7(UINT32 pc, UINT32 insn);
	void tg06_0(UINT32 pc, UINT32 insn);
	void tg06_1(UINT32 pc, UINT32 insn);
	void tg07_0(UINT32 pc, UINT32 insn);
	void tg07_1(UINT32 pc, UINT32 insn);
	void tg08_0(UINT32 pc, UINT32 insn);
	void tg08_1(UINT32 pc, UINT32 insn);
	void tg09_0(UINT32 pc, UINT32 insn);
	void tg09_1(UINT32 pc, UINT32 insn);
	void tg0a_0(UINT32 pc, UINT32 insn);
	void tg0a_1(UINT32 pc, UINT32 insn);
	void tg0b_0(UINT32 pc, UINT32 insn);
	void tg0b_1(UINT32 pc, UINT32 insn);
	void tg0b_2(UINT32 pc, UINT32 insn);
	void tg0b_3(UINT32 pc, UINT32 insn);
	void tg0b_4(UINT32 pc, UINT32 insn);
	void tg0b_5(UINT32 pc, UINT32 insn);
	void tg0b_6(UINT32 pc, UINT32 insn);
	void tg0b_7(UINT32 pc, UINT32 insn);
	void tg0b_8(UINT32 pc, UINT32 insn);
	void tg0b_9(UINT32 pc, UINT32 insn);
	void tg0b_a(UINT32 pc, UINT32 insn);
	void tg0b_b(UINT32 pc, UINT32 insn);
	void tg0b_c(UINT32 pc, UINT32 insn);
	void tg0b_d(UINT32 pc, UINT32 insn);
	void tg0b_e(UINT32 pc, UINT32 insn);
	void tg0b_f(UINT32 pc, UINT32 insn);
	void tg0c_0(UINT32 pc, UINT32 insn);
	void tg0c_1(UINT32 pc, UINT32 insn);
	void tg0d_0(UINT32 pc, UINT32 insn);
	void tg0d_1(UINT32 pc, UINT32 insn);
	void tg0d_2(UINT32 pc, UINT32 insn);
	void tg0d_3(UINT32 pc, UINT32 insn);
	void tg0d_4(UINT32 pc, UINT32 insn);
	void tg0d_5(UINT32 pc, UINT32 insn);
	void tg0d_6(UINT32 pc, UINT32 insn);
	void tg0d_7(UINT32 pc, UINT32 insn);
	void tg0d_8(UINT32 pc, UINT32 insn);
	void tg0d_9(UINT32 pc, UINT32 insn);
	void tg0d_a(UINT32 pc, UINT32 insn);
	void tg0d_b(UINT32 pc, UINT32 insn);
	void tg0d_c(UINT32 pc, UINT32 insn);
	void tg0d_d(UINT32 pc, UINT32 insn);
	void tg0d_e(UINT32 pc, UINT32 insn);
	void tg0d_f(UINT32 pc, UINT32 insn);
	void tg0e_0(UINT32 pc, UINT32 insn);
	void tg0e_1(UINT32 pc, UINT32 insn);
	void tg0f_0(UINT32 pc, UINT32 insn);
	void tg0f_1(UINT32 pc, UINT32 insn);

	typedef void ( arm7_cpu_device::*arm7thumb_ophandler ) (UINT32, UINT32);
	static const arm7thumb_ophandler thumb_handler[0x40*0x10];

	typedef void ( arm7_cpu_device::*arm7ops_ophandler )(UINT32);
	static const arm7ops_ophandler ops_handler[0x10];

	//
	// DRC
	//

	/* fast RAM info */
	struct fast_ram_info
	{
		offs_t              start;                      /* start of the RAM block */
		offs_t              end;                        /* end of the RAM block */
		UINT8               readonly;                   /* TRUE if read-only */
		void *              base;                       /* base in memory where the RAM lives */
	};

	struct hotspot_info
	{
		UINT32             pc;
		UINT32             opcode;
		UINT32             cycles;
	};

	/* internal compiler state */
	struct compiler_state
	{
		UINT32              cycles;                     /* accumulated cycles */
		UINT8               checkints;                  /* need to check interrupts before next instruction */
		UINT8               checksoftints;              /* need to check software interrupts before next instruction */
		uml::code_label  labelnum;                   /* index for local labels */
	};

	/* ARM7 registers */
	struct arm7imp_state
	{
		/* core state */
		drc_cache *         cache;                      /* pointer to the DRC code cache */
		drcuml_state *      drcuml;                     /* DRC UML generator state */
		//arm7_frontend *     drcfe;                      /* pointer to the DRC front-end state */
		UINT32              drcoptions;                 /* configurable DRC options */

		/* internal stuff */
		UINT8               cache_dirty;                /* true if we need to flush the cache */
		UINT32              jmpdest;                    /* destination jump target */

		/* parameters for subroutines */
		UINT64              numcycles;                  /* return value from gettotalcycles */
		UINT32              mode;                       /* current global mode */
		const char *        format;                     /* format string for print_debug */
		UINT32              arg0;                       /* print_debug argument 1 */
		UINT32              arg1;                       /* print_debug argument 2 */

		/* register mappings */
		uml::parameter   regmap[/*NUM_REGS*/37];               /* parameter to register mappings for all 16 integer registers */

		/* subroutines */
		uml::code_handle *   entry;                      /* entry point */
		uml::code_handle *   nocode;                     /* nocode exception handler */
		uml::code_handle *   out_of_cycles;              /* out of cycles exception handler */
		uml::code_handle *   tlb_translate;              /* tlb translation handler */
		uml::code_handle *   detect_fault;               /* tlb fault detection handler */
		uml::code_handle *   check_irq;                  /* irq check handler */
		uml::code_handle *   read8;                      /* read byte */
		uml::code_handle *   write8;                     /* write byte */
		uml::code_handle *   read16;                     /* read half */
		uml::code_handle *   write16;                    /* write half */
		uml::code_handle *   read32;                     /* read word */
		uml::code_handle *   write32;                    /* write word */

		/* fast RAM */
		UINT32              fastram_select;
		fast_ram_info       fastram[ARM7_MAX_FASTRAM];

		/* hotspots */
		UINT32              hotspot_select;
		hotspot_info        hotspot[ARM7_MAX_HOTSPOTS];
	} m_impstate;

	typedef void ( arm7_cpu_device::*arm7thumb_drcophandler)(drcuml_block*, compiler_state*, const opcode_desc*);
	static const arm7thumb_drcophandler drcthumb_handler[0x40*0x10];

	void drctg00_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* Shift left */
	void drctg00_1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* Shift right */
	void drctg01_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void drctg01_10(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void drctg01_11(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* SUB Rd, Rs, Rn */
	void drctg01_12(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* ADD Rd, Rs, #imm */
	void drctg01_13(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* SUB Rd, Rs, #imm */
	void drctg02_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void drctg02_1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void drctg03_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* ADD Rd, #Offset8 */
	void drctg03_1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* SUB Rd, #Offset8 */
	void drctg04_00_00(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* AND Rd, Rs */
	void drctg04_00_01(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* EOR Rd, Rs */
	void drctg04_00_02(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* LSL Rd, Rs */
	void drctg04_00_03(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* LSR Rd, Rs */
	void drctg04_00_04(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* ASR Rd, Rs */
	void drctg04_00_05(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* ADC Rd, Rs */
	void drctg04_00_06(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);  /* SBC Rd, Rs */
	void drctg04_00_07(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* ROR Rd, Rs */
	void drctg04_00_08(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* TST Rd, Rs */
	void drctg04_00_09(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* NEG Rd, Rs */
	void drctg04_00_0a(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* CMP Rd, Rs */
	void drctg04_00_0b(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* CMN Rd, Rs - check flags, add dasm */
	void drctg04_00_0c(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* ORR Rd, Rs */
	void drctg04_00_0d(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* MUL Rd, Rs */
	void drctg04_00_0e(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* BIC Rd, Rs */
	void drctg04_00_0f(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* MVN Rd, Rs */
	void drctg04_01_00(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void drctg04_01_01(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* ADD Rd, HRs */
	void drctg04_01_02(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* ADD HRd, Rs */
	void drctg04_01_03(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* Add HRd, HRs */
	void drctg04_01_10(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);  /* CMP Rd, Rs */
	void drctg04_01_11(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* CMP Rd, Hs */
	void drctg04_01_12(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* CMP Hd, Rs */
	void drctg04_01_13(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* CMP Hd, Hs */
	void drctg04_01_20(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* MOV Rd, Rs (undefined) */
	void drctg04_01_21(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* MOV Rd, Hs */
	void drctg04_01_22(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* MOV Hd, Rs */
	void drctg04_01_23(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* MOV Hd, Hs */
	void drctg04_01_30(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void drctg04_01_31(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void drctg04_01_32(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void drctg04_01_33(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void drctg04_0203(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void drctg05_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);  /* STR Rd, [Rn, Rm] */
	void drctg05_1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);  /* STRH Rd, [Rn, Rm] */
	void drctg05_2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);  /* STRB Rd, [Rn, Rm] */
	void drctg05_3(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);  /* LDSB Rd, [Rn, Rm] todo, add dasm */
	void drctg05_4(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);  /* LDR Rd, [Rn, Rm] */
	void drctg05_5(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);  /* LDRH Rd, [Rn, Rm] */
	void drctg05_6(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);  /* LDRB Rd, [Rn, Rm] */
	void drctg05_7(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);  /* LDSH Rd, [Rn, Rm] */
	void drctg06_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* Store */
	void drctg06_1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* Load */
	void drctg07_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* Store */
	void drctg07_1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);  /* Load */
	void drctg08_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* Store */
	void drctg08_1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* Load */
	void drctg09_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* Store */
	void drctg09_1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* Load */
	void drctg0a_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);  /* ADD Rd, PC, #nn */
	void drctg0a_1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* ADD Rd, SP, #nn */
	void drctg0b_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* ADD SP, #imm */
	void drctg0b_1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void drctg0b_2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void drctg0b_3(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void drctg0b_4(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* PUSH {Rlist} */
	void drctg0b_5(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* PUSH {Rlist}{LR} */
	void drctg0b_6(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void drctg0b_7(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void drctg0b_8(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void drctg0b_9(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void drctg0b_a(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void drctg0b_b(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void drctg0b_c(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* POP {Rlist} */
	void drctg0b_d(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* POP {Rlist}{PC} */
	void drctg0b_e(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void drctg0b_f(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void drctg0c_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* Store */
	void drctg0c_1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* Load */
	void drctg0d_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // COND_EQ:
	void drctg0d_1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // COND_NE:
	void drctg0d_2(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // COND_CS:
	void drctg0d_3(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // COND_CC:
	void drctg0d_4(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // COND_MI:
	void drctg0d_5(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // COND_PL:
	void drctg0d_6(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // COND_VS:
	void drctg0d_7(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // COND_VC:
	void drctg0d_8(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // COND_HI:
	void drctg0d_9(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // COND_LS:
	void drctg0d_a(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // COND_GE:
	void drctg0d_b(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // COND_LT:
	void drctg0d_c(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // COND_GT:
	void drctg0d_d(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // COND_LE:
	void drctg0d_e(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // COND_AL:
	void drctg0d_f(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); // SWI (this is sort of a "hole" in the opcode encoding)
	void drctg0e_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void drctg0e_1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void drctg0f_0(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void drctg0f_1(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); /* BL */

	void load_fast_iregs(drcuml_block *block);
	void save_fast_iregs(drcuml_block *block);
	void arm7_drc_init();
	void arm7_drc_exit();
	void execute_run_drc();
	void arm7drc_set_options(UINT32 options);
	void arm7drc_add_fastram(offs_t start, offs_t end, UINT8 readonly, void *base);
	void arm7drc_add_hotspot(offs_t pc, UINT32 opcode, UINT32 cycles);
	void code_flush_cache();
	void code_compile_block(UINT8 mode, offs_t pc);
	void cfunc_get_cycles();
	void cfunc_unimplemented();
	void static_generate_entry_point();
	void static_generate_check_irq();
	void static_generate_nocode_handler();
	void static_generate_out_of_cycles();
	void static_generate_detect_fault(uml::code_handle **handleptr);
	void static_generate_tlb_translate(uml::code_handle **handleptr);
	void static_generate_memory_accessor(int size, bool istlb, bool iswrite, const char *name, uml::code_handle **handleptr);
	void generate_update_cycles(drcuml_block *block, compiler_state *compiler, uml::parameter param);
	void generate_checksum_block(drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast);
	void generate_sequence_instruction(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
	void generate_delay_slot_and_branch(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT8 linkreg);

	typedef bool ( arm7_cpu_device::*drcarm7ops_ophandler)(drcuml_block*, compiler_state*, const opcode_desc*, UINT32);
	static const drcarm7ops_ophandler drcops_handler[0x10];

	void saturate_qbit_overflow(drcuml_block *block);
	bool drcarm7ops_0123(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 op);
	bool drcarm7ops_4567(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 op);
	bool drcarm7ops_89(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 op);
	bool drcarm7ops_ab(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 op);
	bool drcarm7ops_cd(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 op);
	bool drcarm7ops_e(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 op);
	bool drcarm7ops_f(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 op);
	int generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);

};


class arm7_be_cpu_device : public arm7_cpu_device
{
public:
	// construction/destruction
	arm7_be_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);

};


class arm7500_cpu_device : public arm7_cpu_device
{
public:
	// construction/destruction
	arm7500_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);

};


class arm9_cpu_device : public arm7_cpu_device
{
public:
	// construction/destruction
	arm9_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);

};


class arm920t_cpu_device : public arm7_cpu_device
{
public:
	// construction/destruction
	arm920t_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);

};


class pxa255_cpu_device : public arm7_cpu_device
{
public:
	// construction/destruction
	pxa255_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);

};


class sa1110_cpu_device : public arm7_cpu_device
{
public:
	// construction/destruction
	sa1110_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);

};


extern const device_type ARM7;
extern const device_type ARM7_BE;
extern const device_type ARM7500;
extern const device_type ARM9;
extern const device_type ARM920T;
extern const device_type PXA255;
extern const device_type SA1110;

#endif /* __ARM7_H__ */