Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/yabause/src/dreamcast/sh2rec/sh2rec.c
2 views
1
/* Copyright 2010 Lawrence Sebald
2
3
This file is part of Yabause.
4
5
Yabause is free software; you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation; either version 2 of the License, or
8
(at your option) any later version.
9
10
Yabause is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU General Public License for more details.
14
15
You should have received a copy of the GNU General Public License
16
along with Yabause; if not, write to the Free Software
17
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
*/
19
20
/* SH2 Dynarec Core (for SH4) */
21
22
#include <stdio.h>
23
#include <stdlib.h>
24
#include <inttypes.h>
25
#include <arch/cache.h>
26
27
#include "sh2core.h"
28
#include "sh2rec.h"
29
#include "sh2rec_htab.h"
30
#include "sh2int.h"
31
32
/* Registers */
33
#define R0 0
34
#define R1 1
35
#define R2 2
36
#define R3 3
37
#define R4 4
38
#define R5 5
39
#define R6 6
40
#define R7 7
41
#define R8 8
42
#define R9 9
43
#define R10 10
44
#define R11 11
45
#define R12 12
46
#define R13 13
47
#define R14 14
48
#define R15 15
49
50
/* Control Registers (use with emitSTC/emitLDC) */
51
#define R_SR 0
52
#define R_GBR 1
53
#define R_VBR 2
54
55
/* System Registers (use with emitSTS/emitLDS) */
56
#define R_MACH 0
57
#define R_MACL 1
58
#define R_PR 2
59
60
/* ALU Ops, to be used with the emitALU function */
61
#define OP_ADD 0x300C
62
#define OP_ADDC 0x300E
63
#define OP_AND 0x2009
64
#define OP_EXTSB 0x600E
65
#define OP_EXTSW 0x600F
66
#define OP_EXTUB 0x600C
67
#define OP_EXTUW 0x600D
68
#define OP_NEG 0x600B
69
#define OP_NEGC 0x600A
70
#define OP_NOT 0x6007
71
#define OP_OR 0x200B
72
#define OP_SUB 0x3008
73
#define OP_SUBC 0x300A
74
#define OP_SWAPB 0x6008
75
#define OP_SWAPW 0x6009
76
#define OP_XOR 0x200A
77
#define OP_XTRCT 0x200D
78
79
/* Shift/Rotate Ops, to be used with the emitSHIFT function */
80
#define OP_ROTCL 0x4024
81
#define OP_ROTCR 0x4025
82
#define OP_ROTL 0x4004
83
#define OP_ROTR 0x4005
84
#define OP_SHAL 0x4020
85
#define OP_SHAR 0x4021
86
#define OP_SHLL 0x4000
87
#define OP_SHLR 0x4001
88
89
/* Comparison Ops, to be used with the emitALU function */
90
#define OP_CMPEQ 0x3000
91
#define OP_CMPGE 0x3003
92
#define OP_CMPGT 0x3007
93
#define OP_CMPHI 0x3006
94
#define OP_CMPHS 0x3002
95
#define OP_CMPSTR 0x200C
96
#define OP_TST 0x2008
97
98
/* Multiplication ops, to be used with the emitALU function */
99
#define OP_DMULS 0x300D
100
#define OP_DMULU 0x3005
101
#define OP_MULL 0x0007
102
#define OP_MULS 0x200F
103
#define OP_MULU 0x200E
104
105
#ifdef SH2REC__DEBUG
106
#define EMIT_INST {\
107
printf("%s\n", __PRETTY_FUNCTION__); \
108
printf("Emitting %04x at %p\n", inst, (void *)b->ptr); \
109
*b->ptr++ = inst; \
110
}
111
#else
112
#define EMIT_INST *b->ptr++ = inst
113
#endif
114
115
#ifdef SH2REC__DEBUG
116
#define EMIT_32 {\
117
uint32_t *__ptr = (uint32_t *)b->ptr; \
118
printf("%s\n", __PRETTY_FUNCTION__); \
119
printf("Emitting %08x at %p\n", (unsigned int)v, (void *)__ptr); \
120
*__ptr = v; \
121
b->ptr += 2; \
122
}
123
#else
124
#define EMIT_32 uint32_t *__ptr = (uint32_t *)b->ptr; *__ptr = v; b->ptr += 2
125
#endif
126
127
static inline void emit16(sh2rec_block_t *b, uint16_t inst) {
128
EMIT_INST;
129
}
130
131
static inline void emit32(sh2rec_block_t *b, uint32_t v) {
132
EMIT_32;
133
}
134
135
static inline void emitMOV(sh2rec_block_t *b, int m, int n) {
136
uint16_t inst = 0x6003 | (n << 8) | (m << 4);
137
EMIT_INST;
138
}
139
140
static inline void emitMOVWI(sh2rec_block_t *b, int d, int n) {
141
uint16_t inst = 0x9000 | (n << 8) | (d);
142
EMIT_INST;
143
}
144
145
static inline void emitMOVLI(sh2rec_block_t *b, int d, int n) {
146
uint16_t inst = 0xD000 | (n << 8) | (d);
147
EMIT_INST;
148
}
149
150
static inline void emitMOVLS(sh2rec_block_t *b, int m, int n) {
151
uint16_t inst = 0x2002 | (n << 8) | (m << 4);
152
EMIT_INST;
153
}
154
155
static inline void emitMOVLL(sh2rec_block_t *b, int m, int n) {
156
uint16_t inst = 0x6002 | (n << 8) | (m << 4);
157
EMIT_INST;
158
}
159
160
static inline void emitMOVWM(sh2rec_block_t *b, int m, int n) {
161
uint16_t inst = 0x2005 | (n << 8) | (m << 4);
162
EMIT_INST;
163
}
164
165
static inline void emitMOVLM(sh2rec_block_t *b, int m, int n) {
166
uint16_t inst = 0x2006 | (n << 8) | (m << 4);
167
EMIT_INST;
168
}
169
170
static inline void emitMOVLP(sh2rec_block_t *b, int m, int n) {
171
uint16_t inst = 0x6006 | (n << 8) | (m << 4);
172
EMIT_INST;
173
}
174
175
static inline void emitMOVI(sh2rec_block_t *b, int imm, int n) {
176
uint16_t inst = 0xE000 | (n << 8) | (imm & 0xFF);
177
EMIT_INST;
178
}
179
180
static inline void emitMOVLL4(sh2rec_block_t *b, int m, int d, int n) {
181
uint16_t inst = 0x5000 | (n << 8) | (m << 4) | (d);
182
EMIT_INST;
183
}
184
185
static inline void emitMOVLS4(sh2rec_block_t *b, int m, int d, int n) {
186
uint16_t inst = 0x1000 | (n << 8) | (m << 4) | (d);
187
EMIT_INST;
188
}
189
190
static inline void emitMOVLLG(sh2rec_block_t *b, int imm) {
191
uint16_t inst = 0xC600 | (imm & 0xFF);
192
EMIT_INST;
193
}
194
195
static inline void emitMOVLSG(sh2rec_block_t *b, int imm) {
196
uint16_t inst = 0xC200 | (imm & 0xFF);
197
EMIT_INST;
198
}
199
200
static inline void emitMOVT(sh2rec_block_t *b, int n) {
201
uint16_t inst = 0x0029 | (n << 8);
202
EMIT_INST;
203
}
204
205
static inline void emitALU(sh2rec_block_t *b, int m, int n, uint16_t op) {
206
uint16_t inst = (n << 8) | (m << 4) | op;
207
EMIT_INST;
208
}
209
210
static inline void emitSHIFT(sh2rec_block_t *b, int n, uint16_t op) {
211
uint16_t inst = (n << 8) | op;
212
EMIT_INST;
213
}
214
215
static inline void emitADDI(sh2rec_block_t *b, int imm, int n) {
216
uint16_t inst = 0x7000 | (n << 8) | (imm & 0xFF);
217
EMIT_INST;
218
}
219
220
static inline void emitANDI(sh2rec_block_t *b, int imm) {
221
uint16_t inst = 0xC900 | (imm & 0xFF);
222
EMIT_INST;
223
}
224
225
static inline void emitORI(sh2rec_block_t *b, int imm) {
226
uint16_t inst = 0xCB00 | (imm & 0xFF);
227
EMIT_INST;
228
}
229
230
static inline void emitXORI(sh2rec_block_t *b, int imm) {
231
uint16_t inst = 0xCA00 | (imm & 0xFF);
232
EMIT_INST;
233
}
234
235
static inline void emitSHLL2(sh2rec_block_t *b, int n) {
236
uint16_t inst = 0x4008 | (n << 8);
237
EMIT_INST;
238
}
239
240
static inline void emitSHLL8(sh2rec_block_t *b, int n) {
241
uint16_t inst = 0x4018 | (n << 8);
242
EMIT_INST;
243
}
244
245
static inline void emitSHLL16(sh2rec_block_t *b, int n) {
246
uint16_t inst = 0x4028 | (n << 8);
247
EMIT_INST;
248
}
249
250
static inline void emitSHLR2(sh2rec_block_t *b, int n) {
251
uint16_t inst = 0x4009 | (n << 8);
252
EMIT_INST;
253
}
254
255
static inline void emitSHLR8(sh2rec_block_t *b, int n) {
256
uint16_t inst = 0x4019 | (n << 8);
257
EMIT_INST;
258
}
259
260
static inline void emitSHLR16(sh2rec_block_t *b, int n) {
261
uint16_t inst = 0x4029 | (n << 8);
262
EMIT_INST;
263
}
264
265
static inline void emitCMPIM(sh2rec_block_t *b, int imm) {
266
uint16_t inst = 0x8800 | (imm & 0xFF);
267
EMIT_INST;
268
}
269
270
static inline void emitCMPPL(sh2rec_block_t *b, int n) {
271
uint16_t inst = 0x4015 | (n << 8);
272
EMIT_INST;
273
}
274
275
static inline void emitCMPPZ(sh2rec_block_t *b, int n) {
276
uint16_t inst = 0x4011 | (n << 8);
277
EMIT_INST;
278
}
279
280
static inline void emitADDV(sh2rec_block_t *b, int m, int n) {
281
uint16_t inst = 0x300F | (n << 8) | (m << 4);
282
EMIT_INST;
283
}
284
285
static inline void emitSUBV(sh2rec_block_t *b, int m, int n) {
286
uint16_t inst = 0x300B | (n << 8) | (m << 4);
287
EMIT_INST;
288
}
289
290
static inline void emitLDS(sh2rec_block_t *b, int m, int sr) {
291
uint16_t inst = 0x400A | (m << 8) | (sr << 4);
292
EMIT_INST;
293
}
294
295
static inline void emitSTS(sh2rec_block_t *b, int sr, int n) {
296
uint16_t inst = 0x000A | (n << 8) | (sr << 4);
297
EMIT_INST;
298
}
299
300
static inline void emitLDC(sh2rec_block_t *b, int m, int sr) {
301
uint16_t inst = 0x400E | (m << 8) | (sr << 4);
302
EMIT_INST;
303
}
304
305
static inline void emitSTC(sh2rec_block_t *b, int sr, int n) {
306
uint16_t inst = 0x0002 | (n << 8) | (sr << 4);
307
EMIT_INST;
308
}
309
310
static inline void emitDT(sh2rec_block_t *b, int n) {
311
uint16_t inst = 0x4010 | (n << 8);
312
EMIT_INST;
313
}
314
315
static inline void emitTSTI(sh2rec_block_t *b, int imm) {
316
uint16_t inst = 0xC800 | (imm & 0xFF);
317
EMIT_INST;
318
}
319
320
static inline void emitBRA(sh2rec_block_t *b, int d) {
321
uint16_t inst = 0xA000 | (d);
322
EMIT_INST;
323
}
324
325
static inline void emitDIV0S(sh2rec_block_t *b, int m, int n) {
326
uint16_t inst = 0x2007 | (n << 8) | (m << 4);
327
EMIT_INST;
328
}
329
330
static inline void emitDIV1(sh2rec_block_t *b, int m, int n) {
331
uint16_t inst = 0x3004 | (n << 8) | (m << 4);
332
EMIT_INST;
333
}
334
335
static inline void emitRTS(sh2rec_block_t *b) {
336
uint16_t inst = 0x000B;
337
EMIT_INST;
338
}
339
340
static inline void emitNOP(sh2rec_block_t *b) {
341
uint16_t inst = 0x0009;
342
EMIT_INST;
343
}
344
345
static inline void emitJSR(sh2rec_block_t *b, int m) {
346
uint16_t inst = 0x400B | (m << 8);
347
EMIT_INST;
348
}
349
350
static inline void emitMACL(sh2rec_block_t *b, int m, int n) {
351
uint16_t inst = 0x000F | (n << 8) | (m << 4);
352
EMIT_INST;
353
}
354
355
static inline void emitMACW(sh2rec_block_t *b, int m, int n) {
356
uint16_t inst = 0x400F | (n << 8) | (m << 4);
357
EMIT_INST;
358
}
359
360
static inline void emitCLRMAC(sh2rec_block_t *b) {
361
uint16_t inst = 0x0028;
362
EMIT_INST;
363
}
364
365
static inline void emitBF(sh2rec_block_t *b, int disp) {
366
uint16_t inst = 0x8B00 | (disp & 0xFF);
367
EMIT_INST;
368
}
369
370
static inline void emitBT(sh2rec_block_t *b, int disp) {
371
uint16_t inst = 0x8900 | (disp & 0xFF);
372
EMIT_INST;
373
}
374
375
static inline void generateALUOP(uint16_t inst, sh2rec_block_t *b, int op) {
376
int regn = INSTRUCTION_B(inst);
377
int regm = INSTRUCTION_C(inst);
378
379
emitMOVLL4(b, R8, regn, R2); /* R2 <- sh2[Rn] */
380
emitMOVLL4(b, R8, regm, R3); /* R3 <- sh2[Rm] */
381
emitALU(b, R3, R2, op); /* R2 <- R2 o R3 */
382
emitMOVLS4(b, R2, regn, R8); /* sh2[Rn] <- R2 */
383
384
++b->cycles; /* 1 Cycle */
385
}
386
387
static inline void generateSHIFT(uint16_t inst, sh2rec_block_t *b, int op) {
388
int regn = INSTRUCTION_B(inst);
389
390
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
391
emitMOVLL4(b, R8, regn, R2); /* R2 <- sh2[Rn] */
392
emitSHIFT(b, R0, OP_ROTCR); /* Rotate SH2's T Bit in place */
393
emitSHIFT(b, R2, op); /* R2 <- R2 op */
394
emitSHIFT(b, R0, OP_ROTCL); /* Rotate T back to SH2 reg */
395
emitMOVLS4(b, R2, regn, R8); /* sh2[Rn] <- R2 */
396
emitMOVLSG(b, 16); /* sh2[SR] <- R0 */
397
398
++b->cycles; /* 1 Cycle */
399
}
400
401
static inline void generateCOMP(uint16_t inst, sh2rec_block_t *b, int op) {
402
int regn = INSTRUCTION_B(inst);
403
int regm = INSTRUCTION_C(inst);
404
405
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
406
emitMOVLL4(b, R8, regn, R2); /* R2 <- sh2[Rn] */
407
emitMOVLL4(b, R8, regm, R3); /* R3 <- sh2[Rm] */
408
emitSHIFT(b, R0, OP_ROTCR); /* Rotate SH2's T Bit in place */
409
emitALU(b, R3, R2, op); /* R2 op R3 */
410
emitSHIFT(b, R0, OP_ROTCL); /* Rotate T back to SH2 reg */
411
emitMOVLSG(b, 16); /* sh2[SR] <- R0 */
412
413
++b->cycles; /* 1 Cycle */
414
}
415
416
static void generateADD(uint16_t inst, sh2rec_block_t *b) {
417
generateALUOP(inst, b, OP_ADD);
418
b->pc += 2;
419
}
420
421
static void generateADDI(uint16_t inst, sh2rec_block_t *b) {
422
int regn = INSTRUCTION_B(inst);
423
int imm = INSTRUCTION_CD(inst);
424
425
emitMOVLL4(b, R8, regn, R2); /* R2 <- sh2[Rn] */
426
emitADDI(b, imm, R2); /* R2 <- R2 + #imm */
427
emitMOVLS4(b, R2, regn, R8); /* sh2[Rn] <- R2 */
428
429
++b->cycles; /* 1 Cycle */
430
b->pc += 2;
431
}
432
433
static void generateADDC(uint16_t inst, sh2rec_block_t *b) {
434
int regn = INSTRUCTION_B(inst);
435
int regm = INSTRUCTION_C(inst);
436
437
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
438
emitMOVLL4(b, R8, regn, R2); /* R2 <- sh2[Rn] */
439
emitMOVLL4(b, R8, regm, R3); /* R3 <- sh2[Rm] */
440
emitSHIFT(b, R0, OP_ROTCR); /* Rotate SH2's T Bit in place */
441
emitALU(b, R3, R2, OP_ADDC); /* R2 = R2 + R3 + T (carry to T) */
442
emitSHIFT(b, R0, OP_ROTCL); /* Rotate T back to SH2 reg */
443
emitMOVLS4(b, R2, regn, R8); /* sh2[Rn] <- R2 */
444
emitMOVLSG(b, 16); /* sh2[SR] <- R0 */
445
446
++b->cycles; /* 1 Cycle */
447
b->pc += 2;
448
}
449
450
static void generateADDV(uint16_t inst, sh2rec_block_t *b) {
451
int regn = INSTRUCTION_B(inst);
452
int regm = INSTRUCTION_C(inst);
453
454
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
455
emitMOVLL4(b, R8, regn, R2); /* R2 <- sh2[Rn] */
456
emitMOVLL4(b, R8, regm, R3); /* R3 <- sh2[Rm] */
457
emitSHIFT(b, R0, OP_ROTCR); /* Rotate SH2's T Bit in place */
458
emitADDV(b, R3, R2); /* R2 = R2 + R3 (overflow to T Bit) */
459
emitSHIFT(b, R0, OP_ROTCL); /* Rotate T back to SH2 reg */
460
emitMOVLS4(b, R2, regn, R8); /* sh2[Rn] <- R2 */
461
emitMOVLSG(b, 16); /* sh2[SR] <- R0 */
462
463
++b->cycles; /* 1 Cycle */
464
b->pc += 2;
465
}
466
467
static void generateAND(uint16_t inst, sh2rec_block_t *b) {
468
generateALUOP(inst, b, OP_AND);
469
b->pc += 2;
470
}
471
472
static void generateANDI(uint16_t inst, sh2rec_block_t *b) {
473
int imm = INSTRUCTION_CD(inst);
474
475
emitMOVLL4(b, R8, 0, R0); /* R0 <- sh2[R0] */
476
emitANDI(b, imm); /* R0 <- R0 & #imm */
477
emitMOVLS4(b, R0, 0, R8); /* sh2[R0] <- R0 */
478
479
++b->cycles; /* 1 Cycle */
480
b->pc += 2;
481
}
482
483
static void generateANDM(uint16_t inst, sh2rec_block_t *b) {
484
int imm = INSTRUCTION_CD(inst);
485
486
emitSTS(b, R_PR, R10); /* R10 <- PR */
487
emitMOVLLG(b, 17); /* R0 <- sh2[GBR] */
488
emitMOVLL4(b, R8, 0, R4); /* R4 <- sh2[R0] */
489
emitMOVLL4(b, R9, 0, R1); /* R1 <- MappedMemoryReadByte */
490
emitALU(b, R0, R4, OP_ADD); /* R4 <- R4 + R0 */
491
emitJSR(b, R1); /* Call MappedMemoryReadByte */
492
emitMOVLM(b, R4, R15); /* Push R4 on the stack (delay slot) */
493
emitMOVLL4(b, R9, 3, R1); /* R1 <- MappedMemoryWriteByte */
494
emitANDI(b, imm); /* R0 <- R0 & #imm */
495
emitMOVLP(b, R15, R4); /* Pop R4 off the stack */
496
emitJSR(b, R1); /* Call MappedMemoryWriteByte */
497
emitMOV(b, R0, R5); /* R5 <- R0 (delay slot) */
498
emitLDS(b, R10, R_PR); /* PR <- R10 */
499
500
b->cycles += 3; /* 3 Cycles */
501
b->pc += 2;
502
}
503
504
static void generateBF(uint16_t inst, sh2rec_block_t *b) {
505
int disp = INSTRUCTION_CD(inst);
506
uint32_t val = b->pc + 2;
507
508
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
509
emitMOVLI(b, 4, R2); /* R2 <- sh2[PC] + 2 */
510
emitSHIFT(b, R0, OP_ROTCR); /* Rotate SH2's T Bit in place */
511
emitMOVI(b, 0, R0); /* R0 <- 0 */
512
emitBT(b, 2); /* Branch around the addition if needed */
513
emitMOVI(b, disp, R0); /* R0 <- displacement */
514
emitSHIFT(b, R0, OP_SHLL); /* R0 <- R0 << 1 */
515
emitADDI(b, 2, R0); /* R0 <- R0 + 2 */
516
emitRTS(b); /* Return to sender! */
517
emitALU(b, R2, R0, OP_ADD); /* R0 <- R0 + R2 (delay slot) */
518
if(((uint32_t)b->ptr) & 0x03)
519
emit16(b, 0); /* Padding if we need it */
520
emit32(b, val); /* The next PC value (if not taken) */
521
522
b->cycles += 2; /* 2 Cycles (if not taken) */
523
/* XXXX: Handle taken case cycle difference */
524
}
525
526
static void generateBFS(uint16_t inst, sh2rec_block_t *b) {
527
int disp = INSTRUCTION_CD(inst);
528
uint32_t val = b->pc + 4;
529
int n = (((uint32_t)b->ptr) & 0x03) ? 3 : 4;
530
531
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
532
emitMOVLI(b, n, R2); /* R2 <- sh2[PC] + 4 */
533
emitSHIFT(b, R0, OP_ROTCR); /* Rotate SH2's T Bit in place */
534
emitMOVI(b, 0, R0); /* R0 <- 0 */
535
emitBT(b, 1); /* Branch around the addition if needed */
536
emitMOVI(b, disp, R0); /* R0 <- displacement */
537
emitSHIFT(b, R0, OP_SHLL); /* R0 <- R0 << 1 */
538
539
if(((uint32_t)b->ptr) & 0x03) {
540
emitBRA(b, 3); /* Branch around the constant */
541
emitALU(b, R2, R0, OP_ADD); /* R0 <- R0 + R2 (delay slot) */
542
emit16(b, 0); /* Padding since we need it */
543
}
544
else {
545
emitBRA(b, 2); /* Branch around the constant */
546
emitALU(b, R2, R0, OP_ADD); /* R0 <- R0 + R2 (delay slot) */
547
}
548
549
emit32(b, val); /* The next PC value (if not taken) */
550
emitMOVLM(b, R0, R15); /* Push the next PC on the stack */
551
552
/* Deal with the delay slot here */
553
b->pc += 2;
554
sh2rec_rec_inst(b, 1);
555
556
emitRTS(b); /* Return to sender! */
557
emitMOVLP(b, R15, R0); /* Pop the next PC (delay slot) */
558
559
++b->cycles; /* 1 Cycle (if not taken) */
560
/* XXXX: Handle taken case cycle difference */
561
}
562
563
static void generateBRA(uint16_t inst, sh2rec_block_t *b) {
564
int disp = INSTRUCTION_BCD(inst);
565
int32_t val;
566
567
if(disp & 0x00000800) {
568
disp |= 0xFFFFF000;
569
}
570
571
val = b->pc + 4 + (disp << 1);
572
573
emitMOVLI(b, 1, R2); /* R2 <- sh2[PC] + 4 + disp */
574
575
if(((uint32_t)b->ptr) & 0x03) {
576
emitBRA(b, 3); /* Branch around the constant */
577
emitMOVLM(b, R2, R15); /* Push the next PC (delay slot) */
578
emit16(b, 0); /* Padding since we need it */
579
}
580
else {
581
emitBRA(b, 2); /* Branch around the constant */
582
emitMOVLM(b, R2, R15); /* Push the next PC (delay slot) */
583
}
584
585
emit32(b, (uint32_t )val); /* The next PC */
586
587
/* Deal with the delay slot */
588
b->pc += 2;
589
sh2rec_rec_inst(b, 1);
590
591
emitRTS(b); /* Return to sender! */
592
emitMOVLP(b, R15, R0); /* Pop the next PC (delay slot) */
593
594
b->cycles += 2; /* 2 Cycles */
595
}
596
597
static void generateBRAF(uint16_t inst, sh2rec_block_t *b) {
598
int regm = INSTRUCTION_B(inst);
599
uint32_t val = b->pc + 4;
600
601
if(((uint32_t)b->ptr) & 0x03) {
602
emitMOVLI(b, 2, R0); /* R0 <- sh2[PC] + 4 */
603
emitMOVLL4(b, R8, regm, R2);/* R2 <- sh2[Rm] */
604
emitBRA(b, 3); /* Branch around the constant */
605
emitALU(b, R0, R2, OP_ADD); /* R2 <- R0 + R2 (delay slot) */
606
emit16(b, 0); /* Padding since we need it */
607
}
608
else {
609
emitMOVLI(b, 1, R0); /* R0 <- sh2[PC] + 4 */
610
emitMOVLL4(b, R8, regm, R2);/* R2 <- sh2[Rm] */
611
emitBRA(b, 2); /* Branch around the constant */
612
emitALU(b, R0, R2, OP_ADD); /* R2 <- R0 + R2 (delay slot) */
613
}
614
615
emit32(b, val); /* The value to use as the base for PC */
616
emitMOVLM(b, R2, R15); /* Push the next PC */
617
618
/* Deal with the delay slot */
619
b->pc += 2;
620
sh2rec_rec_inst(b, 1);
621
622
emitRTS(b); /* Return to sender! */
623
emitMOVLP(b, R15, R0); /* Pop the next PC (delay slot) */
624
625
b->cycles += 2; /* 2 Cycles */
626
}
627
628
static void generateBSR(uint16_t inst, sh2rec_block_t *b) {
629
int disp = INSTRUCTION_BCD(inst);
630
int32_t val;
631
int32_t val2 = b->pc + 4;
632
633
if(disp & 0x00000800) {
634
disp |= 0xFFFFF000;
635
}
636
637
val = b->pc + 4 + (disp << 1);
638
639
if(((uint32_t)b->ptr) & 0x03) {
640
emitMOVLI(b, 2, R2); /* R2 <- sh2[PC] + 4 + disp */
641
emitMOVLI(b, 2, R0); /* R0 <- sh2[PC] + 4 */
642
emitBRA(b, 5); /* Branch around the constant */
643
emitMOVLM(b, R2, R15); /* Push the next PC (delay slot) */
644
emit16(b, 0); /* Padding since we need it */
645
}
646
else {
647
emitMOVLI(b, 1, R2); /* R2 <- sh2[PC] + 4 + disp */
648
emitMOVLI(b, 2, R0); /* R0 <- sh2[PC] + 4 */
649
emitBRA(b, 4); /* Branch around the constant */
650
emitMOVLM(b, R2, R15); /* Push the next PC (delay slot) */
651
}
652
653
emit32(b, (uint32_t)val); /* The next PC */
654
emit32(b, (uint32_t)val2); /* The value for PR */
655
emitMOVLSG(b, 21); /* sh2[PR] <- R0 */
656
657
/* Deal with the delay slot */
658
b->pc += 2;
659
sh2rec_rec_inst(b, 1);
660
661
emitRTS(b); /* Return to sender! */
662
emitMOVLP(b, R15, R0); /* Pop the next PC (delay slot) */
663
664
b->cycles += 2; /* 2 Cycles */
665
}
666
667
static void generateBSRF(uint16_t inst, sh2rec_block_t *b) {
668
int regm = INSTRUCTION_B(inst);
669
uint32_t val = b->pc + 4;
670
671
emitMOVLI(b, 1, R0); /* R0 <- sh2[PC] + 4 */
672
673
if(((uint32_t)b->ptr) & 0x03) {
674
emitBRA(b, 3); /* Branch around the constant */
675
emitMOVLL4(b, R8, regm, R2);/* R2 <- sh2[Rm] (delay slot) */
676
emit16(b, 0); /* Padding since we need it */
677
}
678
else {
679
emitBRA(b, 2); /* Branch around the constant */
680
emitMOVLL4(b, R8, regm, R2);/* R2 <- sh2[Rm] (delay slot) */
681
}
682
683
emit32(b, val); /* The value to put in PR */
684
emitALU(b, R0, R2, OP_ADD); /* R2 <- R0 + R2 (branch target) */
685
emitMOVLSG(b, 21); /* sh2[PR] <- R0 */
686
emitMOVLM(b, R2, R15); /* Push the next PC */
687
688
/* Deal with the delay slot */
689
b->pc += 2;
690
sh2rec_rec_inst(b, 1);
691
692
emitRTS(b); /* Return to sender! */
693
emitMOVLP(b, R15, R0); /* Pop the next PC (delay slot) */
694
695
b->cycles += 2; /* 2 Cycles */
696
}
697
698
static void generateBT(uint16_t inst, sh2rec_block_t *b) {
699
int disp = INSTRUCTION_CD(inst);
700
uint32_t val = b->pc + 2;
701
702
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
703
emitMOVLI(b, 4, R2); /* R2 <- sh2[PC] + 4 */
704
emitSHIFT(b, R0, OP_ROTCR); /* Rotate SH2's T Bit in place */
705
emitMOVI(b, 0, R0); /* R0 <- 0 */
706
emitBF(b, 2); /* Branch around the addition if needed */
707
emitMOVI(b, disp, R0); /* R0 <- displacement */
708
emitSHIFT(b, R0, OP_SHLL); /* R0 <- R0 << 1 */
709
emitADDI(b, 2, R0); /* R0 <- R0 + 2 */
710
emitRTS(b); /* Return to sender! */
711
emitALU(b, R2, R0, OP_ADD); /* R0 <- R0 + R2 (delay slot) */
712
if(((uint32_t)b->ptr) & 0x03)
713
emit16(b, 0); /* Padding if we need it */
714
emit32(b, val); /* The next PC value (if not taken) */
715
716
b->cycles += 2; /* 2 Cycles (if not taken) */
717
/* XXXX: Handle taken case cycle difference */
718
}
719
720
static void generateBTS(uint16_t inst, sh2rec_block_t *b) {
721
int disp = INSTRUCTION_CD(inst);
722
uint32_t val = b->pc + 4;
723
int n = (((uint32_t)b->ptr) & 0x03) ? 3 : 4;
724
725
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
726
emitMOVLI(b, n, R2); /* R2 <- sh2[PC] + 2 */
727
emitSHIFT(b, R0, OP_ROTCR); /* Rotate SH2's T Bit in place */
728
emitMOVI(b, 0, R0); /* R0 <- 0 */
729
emitBF(b, 1); /* Branch around the addition if needed */
730
emitMOVI(b, disp, R0); /* R0 <- displacement */
731
emitSHIFT(b, R0, OP_SHLL); /* R0 <- R0 << 1 */
732
733
if(((uint32_t)b->ptr) & 0x03) {
734
emitBRA(b, 3); /* Branch around the constant */
735
emitALU(b, R2, R0, OP_ADD); /* R0 <- R0 + R2 (delay slot) */
736
emit16(b, 0); /* Padding since we need it */
737
}
738
else {
739
emitBRA(b, 2); /* Branch around the constant */
740
emitALU(b, R2, R0, OP_ADD); /* R0 <- R0 + R2 (delay slot) */
741
}
742
743
emit32(b, val); /* The next PC value (if not taken) */
744
emitMOVLM(b, R0, R15); /* Push the next PC */
745
746
/* Deal with the delay slot */
747
b->pc += 2;
748
sh2rec_rec_inst(b, 1);
749
750
emitRTS(b); /* Return to sender! */
751
emitMOVLP(b, R15, R0); /* Pop the next PC (delay slot) */
752
753
++b->cycles; /* 1 Cycle (if not taken) */
754
/* XXXX: Handle taken case cycle difference */
755
}
756
757
static void generateCLRMAC(uint16_t inst, sh2rec_block_t *b) {
758
emitCLRMAC(b); /* MACL/MACH <- 0 */
759
760
++b->cycles; /* 1 Cycle */
761
b->pc += 2;
762
}
763
764
static void generateCLRT(uint16_t inst, sh2rec_block_t *b) {
765
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
766
emitMOVI(b, 0xFE, R1); /* R1 <- 0xFFFFFFFE */
767
emitALU(b, R3, R0, OP_AND); /* Clear T bit */
768
emitMOVLSG(b, 16); /* sh2[SR] <- R0 */
769
770
++b->cycles; /* 1 Cycle */
771
b->pc += 2;
772
}
773
774
static void generateCMPEQ(uint16_t inst, sh2rec_block_t *b) {
775
generateCOMP(inst, b, OP_CMPEQ);
776
b->pc += 2;
777
}
778
779
static void generateCMPGE(uint16_t inst, sh2rec_block_t *b) {
780
generateCOMP(inst, b, OP_CMPGE);
781
b->pc += 2;
782
}
783
784
static void generateCMPGT(uint16_t inst, sh2rec_block_t *b) {
785
generateCOMP(inst, b, OP_CMPGT);
786
b->pc += 2;
787
}
788
789
static void generateCMPHI(uint16_t inst, sh2rec_block_t *b) {
790
generateCOMP(inst, b, OP_CMPHI);
791
b->pc += 2;
792
}
793
794
static void generateCMPHS(uint16_t inst, sh2rec_block_t *b) {
795
generateCOMP(inst, b, OP_CMPHS);
796
b->pc += 2;
797
}
798
799
static void generateCMPSTR(uint16_t inst, sh2rec_block_t *b) {
800
generateCOMP(inst, b, OP_CMPSTR);
801
b->pc += 2;
802
}
803
804
static void generateCMPPL(uint16_t inst, sh2rec_block_t *b) {
805
int regn = INSTRUCTION_B(inst);
806
807
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
808
emitMOVLL4(b, R8, regn, R2); /* R2 <- sh2[Rn] */
809
emitSHIFT(b, R0, OP_ROTCR); /* Rotate SH2's T Bit in place */
810
emitCMPPL(b, R2); /* cmp/pl R2 */
811
emitSHIFT(b, R0, OP_ROTCL); /* Rotate T back to SH2 reg */
812
emitMOVLSG(b, 16); /* sh2[SR] <- R0 */
813
814
++b->cycles; /* 1 Cycle */
815
b->pc += 2;
816
}
817
818
static void generateCMPPZ(uint16_t inst, sh2rec_block_t *b) {
819
int regn = INSTRUCTION_B(inst);
820
821
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
822
emitMOVLL4(b, R8, regn, R2); /* R2 <- sh2[Rn] */
823
emitSHIFT(b, R0, OP_ROTCR); /* Rotate SH2's T Bit in place */
824
emitCMPPZ(b, R2); /* cmp/pz R2 */
825
emitSHIFT(b, R0, OP_ROTCL); /* Rotate T back to SH2 reg */
826
emitMOVLSG(b, 16); /* sh2[SR] <- R0 */
827
828
++b->cycles; /* 1 Cycle */
829
b->pc += 2;
830
}
831
832
static void generateCMPIM(uint16_t inst, sh2rec_block_t *b) {
833
int imm = INSTRUCTION_CD(inst);
834
835
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
836
emitMOV(b, R0, R2); /* R2 <- R0 */
837
emitMOVLL4(b, R8, 0, R0); /* R0 <- sh2[R0] */
838
emitSHIFT(b, R2, OP_ROTCR); /* Rotate SH2's T Bit in place */
839
emitCMPIM(b, imm); /* cmp/eq R0, #imm */
840
emitSHIFT(b, R2, OP_ROTCL); /* Rotate T back to SH2 reg */
841
emitMOV(b, R2, R0); /* R0 <- R2 */
842
emitMOVLSG(b, 16); /* sh2[SR] <- R0 */
843
844
++b->cycles; /* 1 Cycle */
845
b->pc += 2;
846
}
847
848
static void generateDIV0S(uint16_t inst, sh2rec_block_t *b) {
849
int regn = INSTRUCTION_B(inst);
850
int regm = INSTRUCTION_C(inst);
851
852
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
853
emitMOVLL4(b, R8, regn, R2); /* R2 <- sh2[Rn] */
854
emitMOVI(b, 0x03, R4); /* R4 <- 0x03 */
855
emitANDI(b, 0xF2); /* Clear M, Q, and T */
856
emitMOVLL4(b, R8, regm, R3); /* R3 <- sh2[Rm] */
857
emitSHLL8(b, R4); /* R4 <<= 8 */
858
emitSHIFT(b, R0, OP_SHLR); /* Chop off the T from the SH2 reg */
859
emitDIV0S(b, R3, R2); /* div0s to grab the M, Q, T bits needed */
860
emitSTC(b, R_SR, R5); /* Save SR to R5 */
861
emitALU(b, R4, R5, OP_AND); /* Grab M, Q from the SR */
862
emitSHIFT(b, R0, OP_ROTCL); /* Rotate T back to SH2 reg */
863
emitALU(b, R5, R0, OP_OR); /* Save M, Q into the SH2 reg */
864
emitMOVLSG(b, 16); /* sh2[SR] <- R0 */
865
866
++b->cycles; /* 1 Cycle */
867
b->pc += 2;
868
}
869
870
static void generateDIV0U(uint16_t inst, sh2rec_block_t *b) {
871
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
872
emitANDI(b, 0xF2); /* Mask off M, Q, and T bits */
873
emitMOVLSG(b, 16); /* sh2[SR] <- R0 */
874
875
++b->cycles; /* 1 Cycle */
876
b->pc += 2;
877
}
878
879
static void generateDIV1(uint16_t inst, sh2rec_block_t *b) {
880
int regn = INSTRUCTION_B(inst);
881
int regm = INSTRUCTION_C(inst);
882
883
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
884
emitMOVLL4(b, R8, regn, R2); /* R2 <- sh2[Rn] */
885
emitMOVI(b, 0x03, R4); /* R4 <- 0x03 */
886
emitSHLL8(b, R4); /* R4 <<= 8 */
887
emitMOVLL4(b, R8, regm, R3); /* R3 <- sh2[Rm] */
888
emitMOV(b, R4, R6); /* R6 <- R4 */
889
emitALU(b, R0, R6, OP_AND); /* Grab SH2 M and Q bits */
890
emitSHIFT(b, R0, OP_ROTCR); /* Rotate SH2's T in place */
891
emitSTC(b, R_SR, R5); /* Save SR to R5 */
892
emitALU(b, R4, R7, OP_NOT); /* Set up the mask to clear M and Q */
893
emitALU(b, R7, R5, OP_AND); /* Clear M, Q */
894
emitALU(b, R6, R5, OP_OR); /* Put SH2's M and Q in place */
895
emitLDC(b, R5, R_SR); /* Put the modified SR in place */
896
emitDIV1(b, R3, R2); /* Do the division! */
897
emitSTC(b, R_SR, R5); /* Save updated SR to R5 */
898
emitALU(b, R4, R5, OP_AND); /* Grab M and Q from the SR */
899
emitSHIFT(b, R0, OP_ROTCL); /* Rotate T back to SH2 reg */
900
emitMOVLS4(b, R2, regn, R8); /* sh2[Rn] <- R2 */
901
emitANDI(b, 0xF3); /* Clear M and Q from the SH2 reg */
902
emitALU(b, R5, R0, OP_OR); /* Save M and Q into the SH2 reg */
903
emitMOVLSG(b, 16); /* sh2[SR] <- R0 */
904
905
++b->cycles; /* 1 Cycle */
906
b->pc += 2;
907
}
908
909
static void generateDMULS(uint16_t inst, sh2rec_block_t *b) {
910
int regn = INSTRUCTION_B(inst);
911
int regm = INSTRUCTION_C(inst);
912
913
emitMOVLL4(b, R8, regn, R2); /* R2 <- sh2[Rn] */
914
emitMOVLL4(b, R8, regm, R3); /* R3 <- sh2[Rm] */
915
emitALU(b, R3, R2, OP_DMULS); /* MACH/MACL <- (s32)R2 * (s32)R3 */
916
917
b->cycles += 2; /* 2 Cycles */
918
b->pc += 2;
919
}
920
921
static void generateDMULU(uint16_t inst, sh2rec_block_t *b) {
922
int regn = INSTRUCTION_B(inst);
923
int regm = INSTRUCTION_C(inst);
924
925
emitMOVLL4(b, R8, regn, R2); /* R2 <- sh2[Rn] */
926
emitMOVLL4(b, R8, regm, R3); /* R3 <- sh2[Rm] */
927
emitALU(b, R3, R2, OP_DMULU); /* MACH/MACL <- (u32)R2 * (u32)R3 */
928
929
b->cycles += 2; /* 2 Cycles */
930
b->pc += 2;
931
}
932
933
static void generateDT(uint16_t inst, sh2rec_block_t *b) {
934
int regn = INSTRUCTION_B(inst);
935
936
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
937
emitMOVLL4(b, R8, regn, R2); /* R2 <- sh2[Rn] */
938
emitSHIFT(b, R0, OP_ROTCR); /* Rotate SH2's T Bit in place */
939
emitDT(b, R2); /* R2 = R2 - 1 (T Bit = non-zero) */
940
emitSHIFT(b, R0, OP_ROTCL); /* Rotate T back to SH2 reg */
941
emitMOVLS4(b, R2, regn, R8); /* sh2[Rn] <- R2 */
942
emitMOVLSG(b, 16); /* sh2[SR] <- R0 */
943
944
++b->cycles; /* 1 Cycle */
945
b->pc += 2;
946
}
947
948
static void generateEXTSB(uint16_t inst, sh2rec_block_t *b) {
949
generateALUOP(inst, b, OP_EXTSB);
950
b->pc += 2;
951
}
952
953
static void generateEXTSW(uint16_t inst, sh2rec_block_t *b) {
954
generateALUOP(inst, b, OP_EXTSW);
955
b->pc += 2;
956
}
957
958
static void generateEXTUB(uint16_t inst, sh2rec_block_t *b) {
959
generateALUOP(inst, b, OP_EXTUB);
960
b->pc += 2;
961
}
962
963
static void generateEXTUW(uint16_t inst, sh2rec_block_t *b) {
964
generateALUOP(inst, b, OP_EXTUW);
965
b->pc += 2;
966
}
967
968
static void generateJMP(uint16_t inst, sh2rec_block_t *b) {
969
int regm = INSTRUCTION_B(inst);
970
971
emitMOVLL4(b, R8, regm, R0); /* Grab the next PC value */
972
emitMOVLM(b, R0, R15); /* Push the next PC on the stack */
973
974
/* Deal with the delay slot */
975
b->pc += 2;
976
sh2rec_rec_inst(b, 1);
977
978
emitRTS(b); /* Return to sender! */
979
emitMOVLP(b, R15, R0); /* Pop the next PC (delay slot) */
980
981
b->cycles += 2; /* 2 Cycles */
982
}
983
984
static void generateJSR(uint16_t inst, sh2rec_block_t *b) {
985
int regm = INSTRUCTION_B(inst);
986
uint32_t val = b->pc + 4;
987
988
emitMOVLI(b, 1, R0); /* R0 <- sh2[PC] + 4 */
989
990
if(((uint32_t)b->ptr) & 0x03) {
991
emitBRA(b, 3); /* Branch around the constant */
992
emitMOVLL4(b, R8, regm, R2);/* R2 <- sh2[Rm] (delay slot) */
993
emit16(b, 0); /* Padding since we need it */
994
}
995
else {
996
emitBRA(b, 2); /* Branch around the constant */
997
emitMOVLL4(b, R8, regm, R2);/* R2 <- sh2[Rm] (delay slot) */
998
}
999
1000
emit32(b, val); /* The value to put in PR */
1001
emitMOVLM(b, R2, R15); /* Push the next PC */
1002
emitMOVLSG(b, 21); /* sh2[PR] <- R0 */
1003
1004
/* Deal with the delay slot */
1005
b->pc += 2;
1006
sh2rec_rec_inst(b, 1);
1007
1008
emitRTS(b); /* Return to sender! */
1009
emitMOVLP(b, R15, R0); /* Pop the next PC (delay slot) */
1010
1011
b->cycles += 2; /* 2 Cycles */
1012
}
1013
1014
static void generateLDCSR(uint16_t inst, sh2rec_block_t *b) {
1015
int regm = INSTRUCTION_B(inst);
1016
1017
emitMOVWI(b, 2, R2); /* R2 <- 0x03F3 */
1018
emitMOVLL4(b, R8, regm, R0); /* R0 <- sh2[Rm] */
1019
emitBRA(b, 1); /* Jump beyond the constant */
1020
emitALU(b, R2, R0, OP_AND); /* R0 <- R0 & R2 (delay slot) */
1021
emit16(b, 0x03F3); /* 0x03F3, grabbed by the emitMOVWI */
1022
emitMOVLSG(b, 16); /* sh2[SR] <- R0 */
1023
1024
++b->cycles; /* 1 Cycle */
1025
b->pc += 2;
1026
}
1027
1028
static void generateLDCGBR(uint16_t inst, sh2rec_block_t *b) {
1029
int regm = INSTRUCTION_B(inst);
1030
1031
emitMOVLL4(b, R8, regm, R0); /* R0 <- sh2[Rm] */
1032
emitMOVLSG(b, 17); /* sh2[GBR] <- R0 */
1033
1034
++b->cycles; /* 1 Cycle */
1035
b->pc += 2;
1036
}
1037
1038
static void generateLDCVBR(uint16_t inst, sh2rec_block_t *b) {
1039
int regm = INSTRUCTION_B(inst);
1040
1041
emitMOVLL4(b, R8, regm, R0); /* R0 <- sh2[Rm] */
1042
emitMOVLSG(b, 18); /* sh2[VBR] <- R0 */
1043
1044
++b->cycles; /* 1 Cycle */
1045
b->pc += 2;
1046
}
1047
1048
static void generateLDCMSR(uint16_t inst, sh2rec_block_t *b) {
1049
int regm = INSTRUCTION_B(inst);
1050
1051
emitMOVLL4(b, R9, 2, R0); /* R0 <- MappedMemoryReadLong */
1052
emitSTS(b, R_PR, R10); /* R10 <- PR */
1053
emitMOVLL4(b, R8, regm, R4); /* R4 <- sh2[Rm] */
1054
emitMOVI(b, 4, R1); /* R1 <- 4 */
1055
emitALU(b, R4, R1, OP_ADD); /* R1 <- R4 + R1 */
1056
emitJSR(b, R0); /* Call MappedMemoryReadLong */
1057
emitMOVLS4(b, R1, regm, R8); /* sh2[Rm] <- R1 */
1058
emitLDS(b, R10, R_PR); /* PR <- R10 */
1059
emitMOVWI(b, 2, R2); /* R2 <- 0x03F3 */
1060
emitBRA(b, 1); /* Jump beyond the constant */
1061
emitALU(b, R2, R0, OP_AND); /* R0 <- R0 & R2 (delay slot) */
1062
emit16(b, 0x03F3); /* 0x03F3, grabbed by the emitMOVWI */
1063
emitMOVLSG(b, 16); /* sh2[SR] <- R0 */
1064
1065
b->cycles += 3; /* 3 Cycles */
1066
b->pc += 2;
1067
}
1068
1069
static void generateLDCMGBR(uint16_t inst, sh2rec_block_t *b) {
1070
int regm = INSTRUCTION_B(inst);
1071
1072
emitMOVLL4(b, R9, 2, R0); /* R0 <- MappedMemoryReadLong */
1073
emitSTS(b, R_PR, R10); /* R10 <- PR */
1074
emitMOVLL4(b, R8, regm, R4); /* R4 <- sh2[Rm] */
1075
emitMOVI(b, 4, R1); /* R1 <- 4 */
1076
emitALU(b, R4, R1, OP_ADD); /* R1 <- R4 + R1 */
1077
emitJSR(b, R0); /* Call MappedMemoryReadLong */
1078
emitMOVLS4(b, R1, regm, R8); /* sh2[Rm] <- R1 */
1079
emitLDS(b, R10, R_PR); /* PR <- R10 */
1080
emitMOVLSG(b, 17); /* sh2[GBR] <- R0 */
1081
1082
b->cycles += 3; /* 3 Cycles */
1083
b->pc += 2;
1084
}
1085
1086
static void generateLDCMVBR(uint16_t inst, sh2rec_block_t *b) {
1087
int regm = INSTRUCTION_B(inst);
1088
1089
emitMOVLL4(b, R9, 2, R0); /* R0 <- MappedMemoryReadLong */
1090
emitSTS(b, R_PR, R10); /* R10 <- PR */
1091
emitMOVLL4(b, R8, regm, R4); /* R4 <- sh2[Rm] */
1092
emitMOVI(b, 4, R1); /* R1 <- 4 */
1093
emitALU(b, R4, R1, OP_ADD); /* R1 <- R4 + R1 */
1094
emitJSR(b, R0); /* Call MappedMemoryReadLong */
1095
emitMOVLS4(b, R1, regm, R8); /* sh2[Rm] <- R1 */
1096
emitLDS(b, R10, R_PR); /* PR <- R10 */
1097
emitMOVLSG(b, 18); /* sh2[VBR] <- R0 */
1098
1099
b->cycles += 3; /* 3 Cycles */
1100
b->pc += 2;
1101
}
1102
1103
static void generateLDSMACH(uint16_t inst, sh2rec_block_t *b) {
1104
int regm = INSTRUCTION_B(inst);
1105
1106
emitMOVLL4(b, R8, regm, R0); /* R0 <- sh2[Rm] */
1107
emitLDS(b, R0, R_MACH); /* MACH <- R0 */
1108
1109
++b->cycles; /* 1 Cycle */
1110
b->pc += 2;
1111
}
1112
1113
static void generateLDSMACL(uint16_t inst, sh2rec_block_t *b) {
1114
int regm = INSTRUCTION_B(inst);
1115
1116
emitMOVLL4(b, R8, regm, R0); /* R0 <- sh2[Rm] */
1117
emitLDS(b, R0, R_MACL); /* MACL <- R0 */
1118
1119
++b->cycles; /* 1 Cycle */
1120
b->pc += 2;
1121
}
1122
1123
static void generateLDSPR(uint16_t inst, sh2rec_block_t *b) {
1124
int regm = INSTRUCTION_B(inst);
1125
1126
emitMOVLL4(b, R8, regm, R0); /* R0 <- sh2[Rm] */
1127
emitMOVLSG(b, 21); /* sh2[PR] <- R0 */
1128
1129
++b->cycles; /* 1 Cycle */
1130
b->pc += 2;
1131
}
1132
1133
static void generateLDSMMACH(uint16_t inst, sh2rec_block_t *b) {
1134
int regm = INSTRUCTION_B(inst);
1135
1136
emitMOVLL4(b, R9, 2, R0); /* R0 <- MappedMemoryReadLong */
1137
emitSTS(b, R_PR, R10); /* R10 <- PR */
1138
emitMOVLL4(b, R8, regm, R4); /* R4 <- sh2[Rm] */
1139
emitMOVI(b, 4, R1); /* R1 <- 4 */
1140
emitALU(b, R4, R1, OP_ADD); /* R1 <- R4 + R1 */
1141
emitJSR(b, R0); /* Call MappedMemoryReadLong */
1142
emitMOVLS4(b, R1, regm, R8); /* sh2[Rm] <- R1 */
1143
emitLDS(b, R10, R_PR); /* PR <- R10 */
1144
emitLDS(b, R0, R_MACH); /* MACH <- R0 */
1145
1146
++b->cycles; /* 1 Cycle */
1147
b->pc += 2;
1148
}
1149
1150
static void generateLDSMMACL(uint16_t inst, sh2rec_block_t *b) {
1151
int regm = INSTRUCTION_B(inst);
1152
1153
emitMOVLL4(b, R9, 2, R0); /* R0 <- MappedMemoryReadLong */
1154
emitSTS(b, R_PR, R10); /* R10 <- PR */
1155
emitMOVLL4(b, R8, regm, R4); /* R4 <- sh2[Rm] */
1156
emitMOVI(b, 4, R1); /* R1 <- 4 */
1157
emitALU(b, R4, R1, OP_ADD); /* R1 <- R4 + R1 */
1158
emitJSR(b, R0); /* Call MappedMemoryReadLong */
1159
emitMOVLS4(b, R1, regm, R8); /* sh2[Rm] <- R1 */
1160
emitLDS(b, R10, R_PR); /* PR <- R10 */
1161
emitLDS(b, R0, R_MACL); /* MACL <- R0 */
1162
1163
++b->cycles; /* 1 Cycle */
1164
b->pc += 2;
1165
}
1166
1167
static void generateLDSMPR(uint16_t inst, sh2rec_block_t *b) {
1168
int regm = INSTRUCTION_B(inst);
1169
1170
emitMOVLL4(b, R9, 2, R0); /* R0 <- MappedMemoryReadLong */
1171
emitSTS(b, R_PR, R10); /* R10 <- PR */
1172
emitMOVLL4(b, R8, regm, R4); /* R4 <- sh2[Rm] */
1173
emitMOVI(b, 4, R1); /* R1 <- 4 */
1174
emitALU(b, R4, R1, OP_ADD); /* R1 <- R4 + R1 */
1175
emitJSR(b, R0); /* Call MappedMemoryReadLong */
1176
emitMOVLS4(b, R1, regm, R8); /* sh2[Rm] <- R1 */
1177
emitLDS(b, R10, R_PR); /* PR <- R10 */
1178
emitMOVLSG(b, 21); /* sh2[PR] <- R0 */
1179
1180
++b->cycles; /* 1 Cycle */
1181
b->pc += 2;
1182
}
1183
1184
static void generateMACL(uint16_t inst, sh2rec_block_t *b) {
1185
int regn = INSTRUCTION_B(inst);
1186
int regm = INSTRUCTION_C(inst);
1187
1188
emitSTS(b, R_PR, R10); /* R10 <- PR */
1189
emitMOVLL4(b, R8, regm, R4); /* R4 <- sh2[Rm] */
1190
emitMOVLL4(b, R9, 2, R0); /* R0 <- MappedMemoryReadLong */
1191
emitADDI(b, 4, R4); /* R4 <- R4 + 4 */
1192
emitMOVLS4(b, R4, regm, R8); /* sh2[Rm] <- R4 */
1193
emitJSR(b, R0); /* Call MappedMemoryReadLong */
1194
emitADDI(b, -4, R4); /* R4 <- R4 - 4 (delay slot) */
1195
emitMOVLM(b, R0, R15); /* Push R0 onto the stack */
1196
emitMOVLL4(b, R8, regn, R4); /* R4 <- sh2[Rn] */
1197
emitMOVLL4(b, R9, 2, R0); /* R0 <- MappedMemoryReadLong */
1198
emitADDI(b, 4, R4); /* R4 <- R4 + 4 */
1199
emitMOVLS4(b, R4, regn, R8); /* sh2[Rn] <- R4 */
1200
emitJSR(b, R0); /* Call MappedMemoryReadLong */
1201
emitADDI(b, -4, R4); /* R4 <- R4 - 4 (delay slot) */
1202
emitSTC(b, R_SR, R2); /* R2 <- SR */
1203
emitMOVI(b, 0xFD, R3); /* R3 <- 0xFFFFFFFD */
1204
emitMOVLM(b, R0, R15); /* Push R0 onto the stack */
1205
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
1206
emitALU(b, R2, R3, OP_AND); /* R3 <- R2 & R3 (Mask out S Bit) */
1207
emitANDI(b, 0x02); /* R0 <- R0 & 0x02 (S Bit) */
1208
emitALU(b, R0, R3, OP_OR); /* R3 <- R0 | R3 (Put SH2 S Bit in) */
1209
emitLDC(b, R3, R_SR); /* SR <- R3 */
1210
emitMACL(b, R15, R15); /* Perform the MAC.L */
1211
emitLDC(b, R2, R_SR); /* SR <- R2 */
1212
emitLDS(b, R10, R_PR); /* PR <- R10 */
1213
1214
b->cycles += 3; /* 3 Cycles */
1215
b->pc += 2;
1216
}
1217
1218
static void generateMACW(uint16_t inst, sh2rec_block_t *b) {
1219
int regn = INSTRUCTION_B(inst);
1220
int regm = INSTRUCTION_C(inst);
1221
1222
emitSTS(b, R_PR, R10); /* R10 <- PR */
1223
emitMOVLL4(b, R8, regm, R4); /* R4 <- sh2[Rm] */
1224
emitMOVLL4(b, R9, 1, R0); /* R0 <- MappedMemoryReadWord */
1225
emitADDI(b, 2, R4); /* R4 <- R4 + 2 */
1226
emitMOVLS4(b, R4, regm, R8); /* sh2[Rm] <- R4 */
1227
emitJSR(b, R0); /* Call MappedMemoryReadWord */
1228
emitADDI(b, -2, R4); /* R4 <- R4 - 2 (delay slot) */
1229
emitMOVWM(b, R0, R15); /* Push R0 onto the stack */
1230
emitMOVLL4(b, R8, regn, R4); /* R4 <- sh2[Rn] */
1231
emitMOVLL4(b, R9, 1, R0); /* R0 <- MappedMemoryReadWord */
1232
emitADDI(b, 2, R4); /* R4 <- R4 + 2 */
1233
emitMOVLS4(b, R4, regn, R8); /* sh2[Rn] <- R4 */
1234
emitJSR(b, R0); /* Call MappedMemoryReadWord */
1235
emitADDI(b, -2, R4); /* R4 <- R4 - 2 (delay slot) */
1236
emitMOVWM(b, R0, R15); /* Push R0 onto the stack */
1237
emitSTC(b, R_SR, R2); /* R2 <- SR */
1238
emitMOVI(b, 0xFD, R3); /* R3 <- 0xFFFFFFFD */
1239
emitMOVLM(b, R0, R15); /* Push R0 onto the stack */
1240
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
1241
emitALU(b, R2, R3, OP_AND); /* R3 <- R2 & R3 (Mask out S Bit) */
1242
emitANDI(b, 0x02); /* R0 <- R0 & 0x02 (S Bit) */
1243
emitALU(b, R0, R3, OP_OR); /* R3 <- R0 | R3 (Put SH2 S Bit in) */
1244
emitLDC(b, R3, R_SR); /* SR <- R3 */
1245
emitMACW(b, R15, R15); /* Perform the MAC.W */
1246
emitLDC(b, R2, R_SR); /* SR <- R2 */
1247
emitLDS(b, R10, R_PR); /* PR <- R10 */
1248
1249
b->cycles += 3; /* 3 Cycles */
1250
b->pc += 2;
1251
}
1252
1253
static void generateMOV(uint16_t inst, sh2rec_block_t *b) {
1254
int regn = INSTRUCTION_B(inst);
1255
int regm = INSTRUCTION_C(inst);
1256
1257
emitMOVLL4(b, R8, regm, R2); /* R2 <- sh2[Rm] */
1258
emitMOVLS4(b, R2, regn, R8); /* sh2[Rn] <- R2 */
1259
1260
++b->cycles; /* 1 Cycle */
1261
b->pc += 2;
1262
}
1263
1264
static void generateMOVBS(uint16_t inst, sh2rec_block_t *b) {
1265
int regn = INSTRUCTION_B(inst);
1266
int regm = INSTRUCTION_C(inst);
1267
1268
emitMOVLL4(b, R9, 3, R0); /* R0 <- MappedMemoryWriteByte */
1269
emitMOVLL4(b, R8, regm, R5); /* R5 <- sh2[Rm] */
1270
emitSTS(b, R_PR, R10); /* R10 <- PR */
1271
emitJSR(b, R0); /* Call MappedMemoryWriteByte */
1272
emitMOVLL4(b, R8, regn, R4); /* R4 <- sh2[Rn] */
1273
emitLDS(b, R10, R_PR); /* PR <- R10 */
1274
1275
++b->cycles; /* 1 Cycle */
1276
b->pc += 2;
1277
}
1278
1279
static void generateMOVWS(uint16_t inst, sh2rec_block_t *b) {
1280
int regn = INSTRUCTION_B(inst);
1281
int regm = INSTRUCTION_C(inst);
1282
1283
emitMOVLL4(b, R9, 4, R0); /* R0 <- MappedMemoryWriteWord */
1284
emitMOVLL4(b, R8, regm, R5); /* R5 <- sh2[Rm] */
1285
emitSTS(b, R_PR, R10); /* R10 <- PR */
1286
emitJSR(b, R0); /* Call MappedMemoryWriteWord */
1287
emitMOVLL4(b, R8, regn, R4); /* R4 <- sh2[Rn] */
1288
emitLDS(b, R10, R_PR); /* PR <- R10 */
1289
1290
++b->cycles; /* 1 Cycle */
1291
b->pc += 2;
1292
}
1293
1294
static void generateMOVLS(uint16_t inst, sh2rec_block_t *b) {
1295
int regn = INSTRUCTION_B(inst);
1296
int regm = INSTRUCTION_C(inst);
1297
1298
emitMOVLL4(b, R9, 5, R0); /* R0 <- MappedMemoryWriteLong */
1299
emitMOVLL4(b, R8, regm, R5); /* R5 <- sh2[Rm] */
1300
emitSTS(b, R_PR, R10); /* R10 <- PR */
1301
emitJSR(b, R0); /* Call MappedMemoryWriteLong */
1302
emitMOVLL4(b, R8, regn, R4); /* R4 <- sh2[Rn] */
1303
emitLDS(b, R10, R_PR); /* PR <- R10 */
1304
1305
++b->cycles; /* 1 Cycle */
1306
b->pc += 2;
1307
}
1308
1309
static void generateMOVBL(uint16_t inst, sh2rec_block_t *b) {
1310
int regn = INSTRUCTION_B(inst);
1311
int regm = INSTRUCTION_C(inst);
1312
1313
emitMOVLL4(b, R9, 0, R0); /* R0 <- MappedMemoryReadByte */
1314
emitSTS(b, R_PR, R10); /* R10 <- PR */
1315
emitJSR(b, R0); /* Call MappedMemoryReadByte */
1316
emitMOVLL4(b, R8, regm, R4); /* R4 <- sh2[Rm] */
1317
emitALU(b, R0, R0, OP_EXTSB); /* Sign extend read byte */
1318
emitLDS(b, R10, R_PR); /* PR <- R10 */
1319
emitMOVLS4(b, R0, regn, R8); /* sh2[Rn] <- read byte */
1320
1321
++b->cycles; /* 1 Cycle */
1322
b->pc += 2;
1323
}
1324
1325
static void generateMOVWL(uint16_t inst, sh2rec_block_t *b) {
1326
int regn = INSTRUCTION_B(inst);
1327
int regm = INSTRUCTION_C(inst);
1328
1329
emitMOVLL4(b, R9, 1, R0); /* R0 <- MappedMemoryReadWord */
1330
emitSTS(b, R_PR, R10); /* R10 <- PR */
1331
emitJSR(b, R0); /* Call MappedMemoryReadWord */
1332
emitMOVLL4(b, R8, regm, R4); /* R4 <- sh2[Rm] */
1333
emitALU(b, R0, R0, OP_EXTSW); /* Sign extend read word */
1334
emitLDS(b, R10, R_PR); /* PR <- R10 */
1335
emitMOVLS4(b, R0, regn, R8); /* sh2[Rn] <- read word */
1336
1337
++b->cycles; /* 1 Cycle */
1338
b->pc += 2;
1339
}
1340
1341
static void generateMOVLL(uint16_t inst, sh2rec_block_t *b) {
1342
int regn = INSTRUCTION_B(inst);
1343
int regm = INSTRUCTION_C(inst);
1344
1345
emitMOVLL4(b, R9, 2, R0); /* R0 <- MappedMemoryReadLong */
1346
emitSTS(b, R_PR, R10); /* R10 <- PR */
1347
emitJSR(b, R0); /* Call MappedMemoryReadLong */
1348
emitMOVLL4(b, R8, regm, R4); /* R4 <- sh2[Rm] */
1349
emitLDS(b, R10, R_PR); /* PR <- R10 */
1350
emitMOVLS4(b, R0, regn, R8); /* sh2[Rn] <- read long */
1351
1352
++b->cycles; /* 1 Cycle */
1353
b->pc += 2;
1354
}
1355
1356
static void generateMOVBM(uint16_t inst, sh2rec_block_t *b) {
1357
int regn = INSTRUCTION_B(inst);
1358
int regm = INSTRUCTION_C(inst);
1359
1360
emitMOVLL4(b, R8, regm, R5); /* R5 <- sh2[Rm] */
1361
emitMOVLL4(b, R9, 3, R0); /* R0 <- MappedMemoryWriteByte */
1362
emitMOVLL4(b, R8, regn, R4); /* R4 <- sh2[Rn] */
1363
emitSTS(b, R_PR, R10); /* R10 <- PR */
1364
emitADDI(b, -1, R4); /* R4 -= 1 */
1365
emitJSR(b, R0); /* Call MappedMemoryWriteByte */
1366
emitMOVLS4(b, R4, regn, R8); /* sh2[Rn] <- R4 */
1367
emitLDS(b, R10, R_PR); /* PR <- R10 */
1368
1369
++b->cycles; /* 1 Cycle */
1370
b->pc += 2;
1371
}
1372
1373
static void generateMOVWM(uint16_t inst, sh2rec_block_t *b) {
1374
int regn = INSTRUCTION_B(inst);
1375
int regm = INSTRUCTION_C(inst);
1376
1377
emitMOVLL4(b, R8, regm, R5); /* R5 <- sh2[Rm] */
1378
emitMOVLL4(b, R9, 4, R0); /* R0 <- MappedMemoryWriteWord */
1379
emitMOVLL4(b, R8, regn, R4); /* R4 <- sh2[Rn] */
1380
emitSTS(b, R_PR, R10); /* R10 <- PR */
1381
emitADDI(b, -2, R4); /* R4 -= 2 */
1382
emitJSR(b, R0); /* Call MappedMemoryWriteWord */
1383
emitMOVLS4(b, R4, regn, R8); /* sh2[Rn] <- R4 */
1384
emitLDS(b, R10, R_PR); /* PR <- R10 */
1385
1386
++b->cycles; /* 1 Cycle */
1387
b->pc += 2;
1388
}
1389
1390
static void generateMOVLM(uint16_t inst, sh2rec_block_t *b) {
1391
int regn = INSTRUCTION_B(inst);
1392
int regm = INSTRUCTION_C(inst);
1393
1394
emitMOVLL4(b, R8, regm, R5); /* R5 <- sh2[Rm] */
1395
emitMOVLL4(b, R9, 5, R0); /* R0 <- MappedMemoryWriteLong */
1396
emitMOVLL4(b, R8, regn, R4); /* R4 <- sh2[Rn] */
1397
emitSTS(b, R_PR, R10); /* R10 <- PR */
1398
emitADDI(b, -4, R4); /* R4 -= 4 */
1399
emitJSR(b, R0); /* Call MappedMemoryWriteLong */
1400
emitMOVLS4(b, R4, regn, R8); /* sh2[Rn] <- R4 */
1401
emitLDS(b, R10, R_PR); /* PR <- R10 */
1402
1403
++b->cycles; /* 1 Cycle */
1404
b->pc += 2;
1405
}
1406
1407
static void generateMOVBP(uint16_t inst, sh2rec_block_t *b) {
1408
int regn = INSTRUCTION_B(inst);
1409
int regm = INSTRUCTION_C(inst);
1410
1411
emitSTS(b, R_PR, R10); /* R10 <- PR */
1412
emitMOVLL4(b, R9, 0, R0); /* R0 <- MappedMemoryReadByte */
1413
emitMOVLL4(b, R8, regm, R4); /* R4 <- sh2[Rm] */
1414
emitMOVI(b, 1, R1); /* R1 <- 1 */
1415
emitALU(b, R4, R1, OP_ADD); /* R1 <- R4 + R1 */
1416
emitJSR(b, R0); /* Call MappedMemoryReadByte */
1417
emitMOVLS4(b, R1, regm, R8); /* sh2[Rm] <- R1 */
1418
emitALU(b, R0, R0, OP_EXTSB); /* Sign extend read byte */
1419
emitLDS(b, R10, R_PR); /* PR <- R10 */
1420
emitMOVLS4(b, R0, regn, R8); /* sh2[Rn] <- read byte */
1421
1422
++b->cycles; /* 1 Cycle */
1423
b->pc += 2;
1424
}
1425
1426
static void generateMOVWP(uint16_t inst, sh2rec_block_t *b) {
1427
int regn = INSTRUCTION_B(inst);
1428
int regm = INSTRUCTION_C(inst);
1429
1430
emitSTS(b, R_PR, R10); /* R10 <- PR */
1431
emitMOVLL4(b, R9, 1, R0); /* R0 <- MappedMemoryReadWord */
1432
emitMOVLL4(b, R8, regm, R4); /* R4 <- sh2[Rm] */
1433
emitMOVI(b, 2, R1); /* R1 <- 2 */
1434
emitALU(b, R4, R1, OP_ADD); /* R1 <- R4 + R1 */
1435
emitJSR(b, R0); /* Call MappedMemoryReadWord */
1436
emitMOVLS4(b, R1, regm, R8); /* sh2[Rm] <- R1 */
1437
emitALU(b, R0, R0, OP_EXTSW); /* Sign extend read word */
1438
emitLDS(b, R10, R_PR); /* PR <- R10 */
1439
emitMOVLS4(b, R0, regn, R8); /* sh2[Rn] <- read word */
1440
1441
++b->cycles; /* 1 Cycle */
1442
b->pc += 2;
1443
}
1444
1445
static void generateMOVLP(uint16_t inst, sh2rec_block_t *b) {
1446
int regn = INSTRUCTION_B(inst);
1447
int regm = INSTRUCTION_C(inst);
1448
1449
emitSTS(b, R_PR, R10); /* R10 <- PR */
1450
emitMOVLL4(b, R9, 2, R0); /* R0 <- MappedMemoryReadLong */
1451
emitMOVLL4(b, R8, regm, R4); /* R4 <- sh2[Rm] */
1452
emitMOVI(b, 4, R1); /* R1 <- 4 */
1453
emitALU(b, R4, R1, OP_ADD); /* R1 <- R4 + R1 */
1454
emitJSR(b, R0); /* Call MappedMemoryReadLong */
1455
emitMOVLS4(b, R1, regm, R8); /* sh2[Rm] <- R1 */
1456
emitLDS(b, R10, R_PR); /* PR <- R10 */
1457
emitMOVLS4(b, R0, regn, R8); /* sh2[Rn] <- read long */
1458
1459
++b->cycles; /* 1 Cycle */
1460
b->pc += 2;
1461
}
1462
1463
static void generateMOVBS0(uint16_t inst, sh2rec_block_t *b) {
1464
int regn = INSTRUCTION_B(inst);
1465
int regm = INSTRUCTION_C(inst);
1466
1467
emitMOVLL4(b, R8, regm, R5); /* R5 <- sh2[Rm] */
1468
emitMOVLL4(b, R8, 0, R1); /* R1 <- sh2[R0] */
1469
emitMOVLL4(b, R9, 3, R0); /* R0 <- MappedMemoryWriteByte */
1470
emitSTS(b, R_PR, R10); /* R10 <- PR */
1471
emitMOVLL4(b, R8, regn, R4); /* R4 <- sh2[Rn] */
1472
emitJSR(b, R0); /* Call MappedMemoryWriteByte */
1473
emitALU(b, R1, R4, OP_ADD); /* R4 <- R4 + R1 */
1474
emitLDS(b, R10, R_PR); /* PR <- R10 */
1475
1476
++b->cycles; /* 1 Cycle */
1477
b->pc += 2;
1478
}
1479
1480
static void generateMOVWS0(uint16_t inst, sh2rec_block_t *b) {
1481
int regn = INSTRUCTION_B(inst);
1482
int regm = INSTRUCTION_C(inst);
1483
1484
emitMOVLL4(b, R8, regm, R5); /* R5 <- sh2[Rm] */
1485
emitMOVLL4(b, R8, 0, R1); /* R1 <- sh2[R0] */
1486
emitMOVLL4(b, R9, 4, R0); /* R0 <- MappedMemoryWriteWord */
1487
emitSTS(b, R_PR, R10); /* R10 <- PR */
1488
emitMOVLL4(b, R8, regn, R4); /* R4 <- sh2[Rn] */
1489
emitJSR(b, R0); /* Call MappedMemoryWriteWord */
1490
emitALU(b, R1, R4, OP_ADD); /* R4 <- R4 + R1 */
1491
emitLDS(b, R10, R_PR); /* PR <- R10 */
1492
1493
++b->cycles; /* 1 Cycle */
1494
b->pc += 2;
1495
}
1496
1497
static void generateMOVLS0(uint16_t inst, sh2rec_block_t *b) {
1498
int regn = INSTRUCTION_B(inst);
1499
int regm = INSTRUCTION_C(inst);
1500
1501
emitMOVLL4(b, R8, regm, R5); /* R5 <- sh2[Rm] */
1502
emitMOVLL4(b, R8, 0, R1); /* R1 <- sh2[R0] */
1503
emitMOVLL4(b, R9, 5, R0); /* R0 <- MappedMemoryWriteLong */
1504
emitSTS(b, R_PR, R10); /* R10 <- PR */
1505
emitMOVLL4(b, R8, regn, R4); /* R4 <- sh2[Rn] */
1506
emitJSR(b, R0); /* Call MappedMemoryWriteLong */
1507
emitALU(b, R1, R4, OP_ADD); /* R4 <- R4 + R1 */
1508
emitLDS(b, R10, R_PR); /* PR <- R10 */
1509
1510
++b->cycles; /* 1 Cycle */
1511
b->pc += 2;
1512
}
1513
1514
static void generateMOVBL0(uint16_t inst, sh2rec_block_t *b) {
1515
int regn = INSTRUCTION_B(inst);
1516
int regm = INSTRUCTION_C(inst);
1517
1518
emitSTS(b, R_PR, R10); /* R10 <- PR */
1519
emitMOVLL4(b, R9, 0, R0); /* R0 <- MappedMemoryReadByte */
1520
emitMOVLL4(b, R8, regm, R4); /* R4 <- sh2[Rm] */
1521
emitMOVLL4(b, R8, 0, R1); /* R1 <- sh2[R0] */
1522
emitJSR(b, R0); /* Call MappedMemoryReadByte */
1523
emitALU(b, R1, R4, OP_ADD); /* R4 <- R4 + R1 */
1524
emitALU(b, R0, R0, OP_EXTSB); /* Sign extend read byte */
1525
emitLDS(b, R10, R_PR); /* PR <- R10 */
1526
emitMOVLS4(b, R0, regn, R8); /* sh2[Rn] <- read byte */
1527
1528
++b->cycles; /* 1 Cycle */
1529
b->pc += 2;
1530
}
1531
1532
static void generateMOVWL0(uint16_t inst, sh2rec_block_t *b) {
1533
int regn = INSTRUCTION_B(inst);
1534
int regm = INSTRUCTION_C(inst);
1535
1536
emitSTS(b, R_PR, R10); /* R10 <- PR */
1537
emitMOVLL4(b, R9, 1, R0); /* R0 <- MappedMemoryReadWord */
1538
emitMOVLL4(b, R8, regm, R4); /* R4 <- sh2[Rm] */
1539
emitMOVLL4(b, R8, 0, R1); /* R1 <- sh2[R0] */
1540
emitJSR(b, R0); /* Call MappedMemoryReadWord */
1541
emitALU(b, R1, R4, OP_ADD); /* R4 <- R4 + R1 */
1542
emitALU(b, R0, R0, OP_EXTSW); /* Sign extend read word */
1543
emitLDS(b, R10, R_PR); /* PR <- R10 */
1544
emitMOVLS4(b, R0, regn, R8); /* sh2[Rn] <- read word */
1545
1546
++b->cycles; /* 1 Cycle */
1547
b->pc += 2;
1548
}
1549
1550
static void generateMOVLL0(uint16_t inst, sh2rec_block_t *b) {
1551
int regn = INSTRUCTION_B(inst);
1552
int regm = INSTRUCTION_C(inst);
1553
1554
emitSTS(b, R_PR, R10); /* R10 <- PR */
1555
emitMOVLL4(b, R9, 2, R0); /* R0 <- MappedMemoryReadLong */
1556
emitMOVLL4(b, R8, regm, R4); /* R4 <- sh2[Rm] */
1557
emitMOVLL4(b, R8, 0, R1); /* R1 <- sh2[R0] */
1558
emitJSR(b, R0); /* Call MappedMemoryReadLong */
1559
emitALU(b, R1, R4, OP_ADD); /* R4 <- R4 + R1 */
1560
emitLDS(b, R10, R_PR); /* PR <- R10 */
1561
emitMOVLS4(b, R0, regn, R8); /* sh2[Rn] <- read long */
1562
1563
++b->cycles; /* 1 Cycle */
1564
b->pc += 2;
1565
}
1566
1567
static void generateMOVI(uint16_t inst, sh2rec_block_t *b) {
1568
int regn = INSTRUCTION_B(inst);
1569
int imm = INSTRUCTION_CD(inst);
1570
1571
emitMOVI(b, imm, R2); /* R2 <- #imm */
1572
emitMOVLS4(b, R2, regn, R8); /* sh2[Rn] <- R2 */
1573
1574
++b->cycles; /* 1 Cycle */
1575
b->pc += 2;
1576
}
1577
1578
static void generateMOVWI(uint16_t inst, sh2rec_block_t *b) {
1579
int regn = INSTRUCTION_B(inst);
1580
int imm = INSTRUCTION_CD(inst);
1581
uint32_t addr = b->pc + 4 + (imm << 1);
1582
1583
if(((uint32_t)b->ptr) & 0x03) {
1584
emitMOVLI(b, 1, R4); /* R4 <- calculated effective addr */
1585
emitBRA(b, 2); /* Jump beyond the constant */
1586
emitMOVLL4(b, R9, 1, R0); /* R0 <- MappedMemoryReadWord */
1587
emit32(b, addr); /* MOV.W effective address */
1588
}
1589
else {
1590
emitMOVLI(b, 1, R4); /* R4 <- calculated effective addr */
1591
emitBRA(b, 3); /* Jump beyond the constant */
1592
emitMOVLL4(b, R9, 1, R0); /* R0 <- MappedMemoryReadWord */
1593
emit16(b, 0); /* Padding, for alignment issues */
1594
emit32(b, addr); /* MOV.W effective address */
1595
}
1596
1597
emitSTS(b, R_PR, R10); /* R10 <- PR */
1598
emitJSR(b, R0); /* Call MappedMemoryReadWord */
1599
emitNOP(b); /* XXXX: Nothing to put here */
1600
emitALU(b, R0, R0, OP_EXTSW); /* Sign extend read word */
1601
emitLDS(b, R10, R_PR); /* PR <- R10 */
1602
emitMOVLS4(b, R0, regn, R8); /* sh2[Rn] <- read word */
1603
1604
++b->cycles; /* 1 Cycle */
1605
b->pc += 2;
1606
}
1607
1608
static void generateMOVLI(uint16_t inst, sh2rec_block_t *b) {
1609
int regn = INSTRUCTION_B(inst);
1610
int imm = INSTRUCTION_CD(inst);
1611
uint32_t addr = ((b->pc + 4) & 0xFFFFFFFC) + (imm << 2);
1612
1613
if(((uint32_t)b->ptr) & 0x03) {
1614
emitMOVLI(b, 1, R4); /* R4 <- calculated effective addr */
1615
emitBRA(b, 2); /* Jump beyond the constant */
1616
emitMOVLL4(b, R9, 2, R0); /* R0 <- MappedMemoryReadLong */
1617
emit32(b, addr); /* MOV.L effective address */
1618
}
1619
else {
1620
emitMOVLI(b, 1, R4); /* R4 <- calculated effective addr */
1621
emitBRA(b, 3); /* Jump beyond the constant */
1622
emitMOVLL4(b, R9, 2, R0); /* R0 <- MappedMemoryReadLong */
1623
emit16(b, 0); /* Padding, for alignment issues */
1624
emit32(b, addr); /* MOV.L effective address */
1625
}
1626
1627
emitSTS(b, R_PR, R10); /* R10 <- PR */
1628
emitJSR(b, R0); /* Call MappedMemoryReadLong */
1629
emitNOP(b); /* XXXX: Nothing to put here */
1630
emitLDS(b, R10, R_PR); /* PR <- R10 */
1631
emitMOVLS4(b, R0, regn, R8); /* sh2[Rn] <- read long */
1632
1633
++b->cycles; /* 1 Cycle */
1634
b->pc += 2;
1635
}
1636
1637
static void generateMOVBLG(uint16_t inst, sh2rec_block_t *b) {
1638
int imm = INSTRUCTION_CD(inst);
1639
1640
emitSTS(b, R_PR, R10); /* R10 <- PR */
1641
emitMOVLL4(b, R9, 0, R1); /* R1 <- MappedMemoryReadByte */
1642
emitMOVI(b, imm, R4); /* R4 <- Displacement */
1643
emitMOVLLG(b, 17); /* R0 <- sh2[GBR] */
1644
emitALU(b, R4, R4, OP_EXTUB); /* Zero extend displacement */
1645
emitJSR(b, R1); /* Call MappedMemoryReadByte */
1646
emitALU(b, R0, R4, OP_ADD); /* R4 <- R4 + R0 */
1647
emitALU(b, R0, R0, OP_EXTSB); /* Sign extend read byte */
1648
emitLDS(b, R10, R_PR); /* PR <- R10 */
1649
emitMOVLS4(b, R0, 0, R8); /* sh2[R0] <- read byte */
1650
1651
++b->cycles; /* 1 Cycle */
1652
b->pc += 2;
1653
}
1654
1655
static void generateMOVWLG(uint16_t inst, sh2rec_block_t *b) {
1656
int imm = INSTRUCTION_CD(inst);
1657
1658
emitSTS(b, R_PR, R10); /* R10 <- PR */
1659
emitMOVI(b, imm, R4); /* R4 <- Displacement */
1660
emitMOVLL4(b, R9, 1, R1); /* R1 <- MappedMemoryReadWord */
1661
emitALU(b, R4, R4, OP_EXTUB); /* Zero extend displacement */
1662
emitMOVLLG(b, 17); /* R0 <- sh2[GBR] */
1663
emitSHIFT(b, R4, OP_SHLL); /* Double displacement */
1664
emitJSR(b, R1); /* Call MappedMemoryReadWord */
1665
emitALU(b, R0, R4, OP_ADD); /* R4 <- R4 + R0 */
1666
emitALU(b, R0, R0, OP_EXTSW); /* Sign extend read word */
1667
emitLDS(b, R10, R_PR); /* PR <- R10 */
1668
emitMOVLS4(b, R0, 0, R8); /* sh2[R0] <- read word */
1669
1670
++b->cycles; /* 1 Cycle */
1671
b->pc += 2;
1672
}
1673
1674
static void generateMOVLLG(uint16_t inst, sh2rec_block_t *b) {
1675
int imm = INSTRUCTION_CD(inst);
1676
1677
emitSTS(b, R_PR, R10); /* R10 <- PR */
1678
emitMOVI(b, imm, R4); /* R4 <- Displacement */
1679
emitMOVLL4(b, R9, 2, R1); /* R1 <- MappedMemoryReadLong */
1680
emitALU(b, R4, R4, OP_EXTUB); /* Zero extend displacement */
1681
emitMOVLLG(b, 17); /* R0 <- sh2[GBR] */
1682
emitSHLL2(b, R4); /* Quadruple displacement */
1683
emitJSR(b, R1); /* Call MappedMemoryReadLong */
1684
emitALU(b, R0, R4, OP_ADD); /* R4 <- R4 + R0 */
1685
emitLDS(b, R10, R_PR); /* PR <- R10 */
1686
emitMOVLS4(b, R0, 0, R8); /* sh2[R0] <- read long */
1687
1688
++b->cycles; /* 1 Cycle */
1689
b->pc += 2;
1690
}
1691
1692
static void generateMOVBSG(uint16_t inst, sh2rec_block_t *b) {
1693
int imm = INSTRUCTION_CD(inst);
1694
1695
emitMOVLL4(b, R8, 0, R5); /* R5 <- sh2[R0] */
1696
emitMOVLLG(b, 17); /* R0 <- sh2[GBR] */
1697
emitSTS(b, R_PR, R10); /* R10 <- PR */
1698
emitMOVLL4(b, R9, 3, R1); /* R1 <- MappedMemoryWriteByte */
1699
emitMOVI(b, imm, R4); /* R4 <- Displacement */
1700
emitALU(b, R4, R4, OP_EXTUB); /* Zero extend Displacement */
1701
emitJSR(b, R1); /* Call MappedMemoryWriteByte */
1702
emitALU(b, R0, R4, OP_ADD); /* R4 <- R4 + R0 */
1703
emitLDS(b, R10, R_PR); /* PR <- R10 */
1704
1705
++b->cycles; /* 1 Cycle */
1706
b->pc += 2;
1707
}
1708
1709
static void generateMOVWSG(uint16_t inst, sh2rec_block_t *b) {
1710
int imm = INSTRUCTION_CD(inst);
1711
1712
emitMOVLL4(b, R8, 0, R5); /* R5 <- sh2[R0] */
1713
emitMOVI(b, imm, R4); /* R4 <- Displacement */
1714
emitMOVLLG(b, 17); /* R0 <- sh2[GBR] */
1715
emitALU(b, R4, R4, OP_EXTUB); /* Zero extend Displacement */
1716
emitMOVLL4(b, R9, 4, R1); /* R1 <- MappedMemoryWriteWord */
1717
emitSTS(b, R_PR, R10); /* R10 <- PR */
1718
emitSHIFT(b, R4, OP_SHLL); /* Double displacement */
1719
emitJSR(b, R1); /* Call MappedMemoryWriteWord */
1720
emitALU(b, R0, R4, OP_ADD); /* R4 <- R4 + R0 */
1721
emitLDS(b, R10, R_PR); /* PR <- R10 */
1722
1723
++b->cycles; /* 1 Cycle */
1724
b->pc += 2;
1725
}
1726
1727
static void generateMOVLSG(uint16_t inst, sh2rec_block_t *b) {
1728
int imm = INSTRUCTION_CD(inst);
1729
1730
emitMOVLL4(b, R8, 0, R5); /* R5 <- sh2[R0] */
1731
emitMOVI(b, imm, R4); /* R4 <- Displacement */
1732
emitMOVLLG(b, 17); /* R0 <- sh2[GBR] */
1733
emitALU(b, R4, R4, OP_EXTUB); /* Zero extend Displacement */
1734
emitMOVLL4(b, R9, 5, R1); /* R1 <- MappedMemoryWriteLong */
1735
emitSTS(b, R_PR, R10); /* R10 <- PR */
1736
emitSHLL2(b, R4); /* Quadruple displacement */
1737
emitJSR(b, R1); /* Call MappedMemoryWriteLong */
1738
emitALU(b, R0, R4, OP_ADD); /* R4 <- R4 + R0 */
1739
emitLDS(b, R10, R_PR); /* PR <- R10 */
1740
1741
++b->cycles; /* 1 Cycle */
1742
b->pc += 2;
1743
}
1744
1745
static void generateMOVBS4(uint16_t inst, sh2rec_block_t *b) {
1746
int regn = INSTRUCTION_C(inst);
1747
int imm = INSTRUCTION_D(inst);
1748
1749
emitMOVLL4(b, R8, 0, R5); /* R5 <- sh2[R0] */
1750
emitMOVLL4(b, R9, 3, R1); /* R1 <- MappedMemoryWriteByte */
1751
emitMOVLL4(b, R8, regn, R4); /* R4 <- sh2[Rn] */
1752
emitSTS(b, R_PR, R10); /* R10 <- PR */
1753
emitJSR(b, R1); /* Call MappedMemoryWriteByte */
1754
emitADDI(b, imm, R4); /* R4 <- R4 + displacement */
1755
emitLDS(b, R10, R_PR); /* PR <- R10 */
1756
1757
++b->cycles; /* 1 Cycle */
1758
b->pc += 2;
1759
}
1760
1761
static void generateMOVWS4(uint16_t inst, sh2rec_block_t *b) {
1762
int regn = INSTRUCTION_C(inst);
1763
int imm = INSTRUCTION_D(inst) << 1;
1764
1765
emitMOVLL4(b, R8, 0, R5); /* R5 <- sh2[R0] */
1766
emitMOVLL4(b, R9, 4, R1); /* R1 <- MappedMemoryWriteWord */
1767
emitMOVLL4(b, R8, regn, R4); /* R4 <- sh2[Rn] */
1768
emitSTS(b, R_PR, R10); /* R10 <- PR */
1769
emitJSR(b, R1); /* Call MappedMemoryWriteWord */
1770
emitADDI(b, imm, R4); /* R4 <- R4 + displacement */
1771
emitLDS(b, R10, R_PR); /* PR <- R10 */
1772
1773
++b->cycles; /* 1 Cycle */
1774
b->pc += 2;
1775
}
1776
1777
static void generateMOVLS4(uint16_t inst, sh2rec_block_t *b) {
1778
int regn = INSTRUCTION_B(inst);
1779
int regm = INSTRUCTION_C(inst);
1780
int imm = INSTRUCTION_D(inst) << 2;
1781
1782
emitMOVLL4(b, R8, regm, R5); /* R5 <- sh2[Rm] */
1783
emitMOVLL4(b, R9, 5, R1); /* R1 <- MappedMemoryWriteLong */
1784
emitMOVLL4(b, R8, regn, R4); /* R4 <- sh2[Rn] */
1785
emitSTS(b, R_PR, R10); /* R10 <- PR */
1786
emitJSR(b, R1); /* Call MappedMemoryWriteLong */
1787
emitADDI(b, imm, R4); /* R4 <- R4 + displacement */
1788
emitLDS(b, R10, R_PR); /* PR <- R10 */
1789
1790
++b->cycles; /* 1 Cycle */
1791
b->pc += 2;
1792
}
1793
1794
static void generateMOVBL4(uint16_t inst, sh2rec_block_t *b) {
1795
int regm = INSTRUCTION_C(inst);
1796
int imm = INSTRUCTION_D(inst);
1797
1798
emitMOVLL4(b, R8, regm, R4); /* R4 <- sh2[Rm] */
1799
emitMOVLL4(b, R9, 0, R1); /* R1 <- MappedMemoryReadByte */
1800
emitSTS(b, R_PR, R10); /* R10 <- PR */
1801
emitJSR(b, R1); /* Call MappedMemoryReadByte */
1802
emitADDI(b, imm, R4); /* R4 <- R4 + displacement */
1803
emitALU(b, R0, R0, OP_EXTSB); /* Sign extend read byte */
1804
emitLDS(b, R10, R_PR); /* PR <- R10 */
1805
emitMOVLS4(b, R0, 0, R8); /* sh2[R0] <- read byte */
1806
1807
++b->cycles; /* 1 Cycle */
1808
b->pc += 2;
1809
}
1810
1811
static void generateMOVWL4(uint16_t inst, sh2rec_block_t *b) {
1812
int regm = INSTRUCTION_C(inst);
1813
int imm = INSTRUCTION_D(inst) << 1;
1814
1815
emitMOVLL4(b, R8, regm, R4); /* R4 <- sh2[Rm] */
1816
emitMOVLL4(b, R9, 1, R1); /* R1 <- MappedMemoryReadWord */
1817
emitSTS(b, R_PR, R10); /* R10 <- PR */
1818
emitJSR(b, R1); /* Call MappedMemoryReadWord */
1819
emitADDI(b, imm, R4); /* R4 <- R4 + displacement */
1820
emitALU(b, R0, R0, OP_EXTSW); /* Sign extend read word */
1821
emitLDS(b, R10, R_PR); /* PR <- R10 */
1822
emitMOVLS4(b, R0, 0, R8); /* sh2[R0] <- read word */
1823
1824
++b->cycles; /* 1 Cycle */
1825
b->pc += 2;
1826
}
1827
1828
static void generateMOVLL4(uint16_t inst, sh2rec_block_t *b) {
1829
int regn = INSTRUCTION_B(inst);
1830
int regm = INSTRUCTION_C(inst);
1831
int imm = INSTRUCTION_D(inst) << 2;
1832
1833
emitMOVLL4(b, R8, regm, R4); /* R4 <- sh2[Rm] */
1834
emitMOVLL4(b, R9, 2, R1); /* R1 <- MappedMemoryReadLong */
1835
emitSTS(b, R_PR, R10); /* R10 <- PR */
1836
emitJSR(b, R1); /* Call MappedMemoryReadLong */
1837
emitADDI(b, imm, R4); /* R4 <- R4 + displacement */
1838
emitLDS(b, R10, R_PR); /* PR <- R10 */
1839
emitMOVLS4(b, R0, regn, R8); /* sh2[Rn] <- read long */
1840
1841
++b->cycles; /* 1 Cycle */
1842
b->pc += 2;
1843
}
1844
1845
static void generateMOVA(uint16_t inst, sh2rec_block_t *b) {
1846
int imm = INSTRUCTION_CD(inst);
1847
uint32_t addr = ((b->pc + 4) & 0xFFFFFFFC) + (imm << 2);
1848
1849
if(((uint32_t)b->ptr) & 0x03) {
1850
emitMOVLI(b, 1, R2); /* R2 <- calculated effective addr */
1851
emitBRA(b, 2); /* Jump beyond the constant */
1852
emitMOVLS4(b, R2, 0, R8); /* sh2[R0] <- R2 */
1853
emit32(b, addr); /* MOVA effective address */
1854
}
1855
else {
1856
emitMOVLI(b, 1, R2); /* R2 <- calculated effective addr */
1857
emitBRA(b, 3); /* Jump beyond the constant */
1858
emitMOVLS4(b, R2, 0, R8); /* sh2[R0] <- R2 */
1859
emit16(b, 0); /* Padding, for alignment issues */
1860
emit32(b, addr); /* MOVA effective address */
1861
}
1862
1863
++b->cycles; /* 1 Cycle */
1864
b->pc += 2;
1865
}
1866
1867
static void generateMOVT(uint16_t inst, sh2rec_block_t *b) {
1868
int regn = INSTRUCTION_B(inst);
1869
1870
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
1871
emitANDI(b, 0x01); /* Grab T Bit */
1872
emitMOVLS4(b, R0, regn, R8); /* sh2[Rn] <- T Bit */
1873
1874
++b->cycles; /* 1 Cycle */
1875
b->pc += 2;
1876
}
1877
1878
static void generateMULL(uint16_t inst, sh2rec_block_t *b) {
1879
int regn = INSTRUCTION_B(inst);
1880
int regm = INSTRUCTION_C(inst);
1881
1882
emitMOVLL4(b, R8, regn, R2); /* R2 <- sh2[Rn] */
1883
emitMOVLL4(b, R8, regm, R3); /* R3 <- sh2[Rm] */
1884
emitALU(b, R3, R2, OP_MULL); /* MACL <- R2 * R3 */
1885
1886
b->cycles += 2; /* 2 Cycles */
1887
b->pc += 2;
1888
}
1889
1890
static void generateMULS(uint16_t inst, sh2rec_block_t *b) {
1891
int regn = INSTRUCTION_B(inst);
1892
int regm = INSTRUCTION_C(inst);
1893
1894
emitMOVLL4(b, R8, regn, R2); /* R2 <- sh2[Rn] */
1895
emitMOVLL4(b, R8, regm, R3); /* R3 <- sh2[Rm] */
1896
emitALU(b, R3, R2, OP_MULS); /* MACL <- (s16)R2 * (s16)R3 */
1897
1898
++b->cycles; /* 1 Cycle */
1899
b->pc += 2;
1900
}
1901
1902
static void generateMULU(uint16_t inst, sh2rec_block_t *b) {
1903
int regn = INSTRUCTION_B(inst);
1904
int regm = INSTRUCTION_C(inst);
1905
1906
emitMOVLL4(b, R8, regn, R2); /* R2 <- sh2[Rn] */
1907
emitMOVLL4(b, R8, regm, R3); /* R3 <- sh2[Rm] */
1908
emitALU(b, R3, R2, OP_MULU); /* MACL <- (u16)R2 * (u16)R3 */
1909
1910
++b->cycles; /* 1 Cycle */
1911
b->pc += 2;
1912
}
1913
1914
static void generateNEG(uint16_t inst, sh2rec_block_t *b) {
1915
int regn = INSTRUCTION_B(inst);
1916
int regm = INSTRUCTION_C(inst);
1917
1918
emitMOVLL4(b, R8, regm, R3); /* R3 <- sh2[Rm] */
1919
emitALU(b, R3, R2, OP_NEG); /* R2 <- 0 - R3 */
1920
emitMOVLS4(b, R2, regn, R8); /* sh2[Rn] <- R2 */
1921
1922
++b->cycles; /* 1 Cycle */
1923
b->pc += 2;
1924
}
1925
1926
static void generateNEGC(uint16_t inst, sh2rec_block_t *b) {
1927
int regn = INSTRUCTION_B(inst);
1928
int regm = INSTRUCTION_C(inst);
1929
1930
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
1931
emitMOVLL4(b, R8, regm, R3); /* R3 <- sh2[Rm] */
1932
emitSHIFT(b, R0, OP_ROTCR); /* Rotate SH2's T Bit in place */
1933
emitALU(b, R3, R2, OP_NEGC); /* R2 = 0 - R3 - T (borrow to T) */
1934
emitSHIFT(b, R0, OP_ROTCL); /* Rotate T back to SH2 reg */
1935
emitMOVLS4(b, R2, regn, R8); /* sh2[Rn] <- R2 */
1936
emitMOVLSG(b, 16); /* sh2[SR] <- R0 */
1937
1938
++b->cycles; /* 1 Cycle */
1939
b->pc += 2;
1940
}
1941
1942
static void generateNOP(uint16_t inst, sh2rec_block_t *b) {
1943
++b->cycles; /* 1 Cycle */
1944
b->pc += 2;
1945
}
1946
1947
static void generateNOT(uint16_t inst, sh2rec_block_t *b) {
1948
generateALUOP(inst, b, OP_NOT);
1949
b->pc += 2;
1950
}
1951
1952
static void generateOR(uint16_t inst, sh2rec_block_t *b) {
1953
generateALUOP(inst, b, OP_OR);
1954
b->pc += 2;
1955
}
1956
1957
static void generateORI(uint16_t inst, sh2rec_block_t *b) {
1958
int imm = INSTRUCTION_CD(inst);
1959
1960
emitMOVLL4(b, R8, 0, R0); /* R0 <- sh2[R0] */
1961
emitORI(b, imm); /* R0 <- R0 | #imm */
1962
emitMOVLS4(b, R0, 0, R8); /* sh2[R0] <- R0 */
1963
1964
++b->cycles; /* 1 Cycle */
1965
b->pc += 2;
1966
}
1967
1968
static void generateORM(uint16_t inst, sh2rec_block_t *b) {
1969
int imm = INSTRUCTION_CD(inst);
1970
1971
emitSTS(b, R_PR, R10); /* R10 <- PR */
1972
emitMOVLLG(b, 17); /* R0 <- sh2[GBR] */
1973
emitMOVLL4(b, R8, 0, R4); /* R4 <- sh2[R0] */
1974
emitMOVLL4(b, R9, 0, R1); /* R1 <- MappedMemoryReadByte */
1975
emitALU(b, R0, R4, OP_ADD); /* R4 <- R4 + R0 */
1976
emitJSR(b, R1); /* Call MappedMemoryReadByte */
1977
emitMOVLM(b, R4, R15); /* Push R4 on the stack (delay slot) */
1978
emitMOVLL4(b, R9, 3, R1); /* R1 <- MappedMemoryWriteByte */
1979
emitORI(b, imm); /* R0 <- R0 | #imm */
1980
emitMOVLP(b, R15, R4); /* Pop R4 off the stack */
1981
emitJSR(b, R1); /* Call MappedMemoryWriteByte */
1982
emitMOV(b, R0, R5); /* R5 <- R0 (delay slot) */
1983
emitLDS(b, R10, R_PR); /* PR <- R10 */
1984
1985
b->cycles += 3; /* 3 Cycles */
1986
b->pc += 2;
1987
}
1988
1989
static void generateROTCL(uint16_t inst, sh2rec_block_t *b) {
1990
generateSHIFT(inst, b, OP_ROTCL);
1991
b->pc += 2;
1992
}
1993
1994
static void generateROTCR(uint16_t inst, sh2rec_block_t *b) {
1995
generateSHIFT(inst, b, OP_ROTCR);
1996
b->pc += 2;
1997
}
1998
1999
static void generateROTL(uint16_t inst, sh2rec_block_t *b) {
2000
generateSHIFT(inst, b, OP_ROTL);
2001
b->pc += 2;
2002
}
2003
2004
static void generateROTR(uint16_t inst, sh2rec_block_t *b) {
2005
generateSHIFT(inst, b, OP_ROTR);
2006
b->pc += 2;
2007
}
2008
2009
static void generateRTE(uint16_t inst, sh2rec_block_t *b) {
2010
emitMOVLL4(b, R9, 2, R0); /* R0 <- MappedMemoryReadLong */
2011
emitSTS(b, R_PR, R10); /* R10 <- PR */
2012
emitJSR(b, R0); /* Call MappedMemoryReadLong */
2013
emitMOVLL4(b, R8, 15, R4); /* R4 <- sh2[R15] (delay slot) */
2014
emitMOVLL4(b, R9, 2, R1); /* R1 <- MappedMemoryReadLong */
2015
emitMOVLL4(b, R8, 15, R4); /* R4 <- sh2[R15] */
2016
emitMOVI(b, 4, R2); /* R2 <- 4 */
2017
emitALU(b, R2, R4, OP_ADD); /* R4 <- R4 + R2 */
2018
emitMOVLM(b, R0, R15); /* Push the next PC */
2019
emitALU(b, R4, R2, OP_ADD); /* R2 <- R4 + R2 */
2020
emitJSR(b, R1); /* Call MappedMemoryReadLong */
2021
emitMOVLS4(b, R2, 15, R8); /* sh2[R15] <- R2 (delay slot) */
2022
emitMOVWI(b, 1, R1); /* R1 <- 0x000003F3 */
2023
emitBRA(b, 1); /* Branch around the constant */
2024
emitALU(b, R1, R0, OP_AND); /* R0 <- R0 & R1 */
2025
emit16(b, 0x03F3); /* Mask for SR register */
2026
emitLDS(b, R10, R_PR); /* PR <- R10 */
2027
emitMOVLSG(b, 16); /* sh2[SR] <- R0 */
2028
2029
/* Deal with the delay slot */
2030
b->pc += 2;
2031
sh2rec_rec_inst(b, 1);
2032
2033
emitRTS(b); /* Return to sender! */
2034
emitMOVLP(b, R15, R0); /* Pop the next PC (delay slot) */
2035
2036
b->cycles += 4; /* 4 Cycles */
2037
}
2038
2039
static void generateRTS(uint16_t inst, sh2rec_block_t *b) {
2040
emitMOVLLG(b, 21); /* R0 <- sh2[PR] */
2041
emitMOVLM(b, R0, R15); /* Push the PR on the stack */
2042
2043
/* Deal with the delay slot */
2044
b->pc += 2;
2045
sh2rec_rec_inst(b, 1);
2046
2047
emitRTS(b); /* Return to sender! */
2048
emitMOVLP(b, R15, R0); /* Pop the next PC (delay slot) */
2049
2050
b->cycles += 2; /* 2 Cycles */
2051
}
2052
2053
static void generateSETT(uint16_t inst, sh2rec_block_t *b) {
2054
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
2055
emitORI(b, 0x01); /* Set T Bit */
2056
emitMOVLSG(b, 16); /* sh2[SR] <- R0 */
2057
2058
++b->cycles; /* 1 Cycle */
2059
b->pc += 2;
2060
}
2061
2062
static void generateSHAL(uint16_t inst, sh2rec_block_t *b) {
2063
generateSHIFT(inst, b, OP_SHAL);
2064
b->pc += 2;
2065
}
2066
2067
static void generateSHAR(uint16_t inst, sh2rec_block_t *b) {
2068
generateSHIFT(inst, b, OP_SHAR);
2069
b->pc += 2;
2070
}
2071
2072
static void generateSHLL(uint16_t inst, sh2rec_block_t *b) {
2073
generateSHIFT(inst, b, OP_SHLL);
2074
b->pc += 2;
2075
}
2076
2077
static void generateSHLL2(uint16_t inst, sh2rec_block_t *b) {
2078
int regn = INSTRUCTION_B(inst);
2079
2080
emitMOVLL4(b, R8, regn, R2); /* R2 <- sh2[Rn] */
2081
emitSHLL2(b, R2); /* R2 <- R2 << 2 */
2082
emitMOVLS4(b, R2, regn, R8); /* sh2[Rn] <- R2 */
2083
2084
++b->cycles; /* 1 Cycle */
2085
b->pc += 2;
2086
}
2087
2088
static void generateSHLL8(uint16_t inst, sh2rec_block_t *b) {
2089
int regn = INSTRUCTION_B(inst);
2090
2091
emitMOVLL4(b, R8, regn, R2); /* R2 <- sh2[Rn] */
2092
emitSHLL8(b, R2); /* R2 <- R2 << 8 */
2093
emitMOVLS4(b, R2, regn, R8); /* sh2[Rn] <- R2 */
2094
2095
++b->cycles; /* 1 Cycle */
2096
b->pc += 2;
2097
}
2098
2099
static void generateSHLL16(uint16_t inst, sh2rec_block_t *b) {
2100
int regn = INSTRUCTION_B(inst);
2101
2102
emitMOVLL4(b, R8, regn, R2); /* R2 <- sh2[Rn] */
2103
emitSHLL16(b, R2); /* R2 <- R2 << 16 */
2104
emitMOVLS4(b, R2, regn, R8); /* sh2[Rn] <- R2 */
2105
2106
++b->cycles; /* 1 Cycle */
2107
b->pc += 2;
2108
}
2109
2110
static void generateSHLR(uint16_t inst, sh2rec_block_t *b) {
2111
generateSHIFT(inst, b, OP_SHLR);
2112
b->pc += 2;
2113
}
2114
2115
static void generateSHLR2(uint16_t inst, sh2rec_block_t *b) {
2116
int regn = INSTRUCTION_B(inst);
2117
2118
emitMOVLL4(b, R8, regn, R2); /* R2 <- sh2[Rn] */
2119
emitSHLR2(b, R2); /* R2 <- R2 >> 2 */
2120
emitMOVLS4(b, R2, regn, R8); /* sh2[Rn] <- R2 */
2121
2122
++b->cycles; /* 1 Cycle */
2123
b->pc += 2;
2124
}
2125
2126
static void generateSHLR8(uint16_t inst, sh2rec_block_t *b) {
2127
int regn = INSTRUCTION_B(inst);
2128
2129
emitMOVLL4(b, R8, regn, R2); /* R2 <- sh2[Rn] */
2130
emitSHLR8(b, R2); /* R2 <- R2 >> 8 */
2131
emitMOVLS4(b, R2, regn, R8); /* sh2[Rn] <- R2 */
2132
2133
++b->cycles; /* 1 Cycle */
2134
b->pc += 2;
2135
}
2136
2137
static void generateSHLR16(uint16_t inst, sh2rec_block_t *b) {
2138
int regn = INSTRUCTION_B(inst);
2139
2140
emitMOVLL4(b, R8, regn, R2); /* R2 <- sh2[Rn] */
2141
emitSHLR16(b, R2); /* R2 <- R2 >> 16 */
2142
emitMOVLS4(b, R2, regn, R8); /* sh2[Rn] <- R2 */
2143
2144
++b->cycles; /* 1 Cycle */
2145
b->pc += 2;
2146
}
2147
2148
static void generateSLEEP(uint16_t inst, sh2rec_block_t *b) {
2149
b->cycles += 3; /* 3 Cycles */
2150
b->pc += 2;
2151
}
2152
2153
static void generateSTCSR(uint16_t inst, sh2rec_block_t *b) {
2154
int regn = INSTRUCTION_B(inst);
2155
2156
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
2157
emitMOVLS4(b, R0, regn, R8); /* sh2[Rn] <- R0 */
2158
2159
++b->cycles; /* 1 Cycle */
2160
b->pc += 2;
2161
}
2162
2163
static void generateSTCGBR(uint16_t inst, sh2rec_block_t *b) {
2164
int regn = INSTRUCTION_B(inst);
2165
2166
emitMOVLLG(b, 17); /* R0 <- sh2[GBR] */
2167
emitMOVLS4(b, R0, regn, R8); /* sh2[Rn] <- R0 */
2168
2169
++b->cycles; /* 1 Cycle */
2170
b->pc += 2;
2171
}
2172
2173
static void generateSTCVBR(uint16_t inst, sh2rec_block_t *b) {
2174
int regn = INSTRUCTION_B(inst);
2175
2176
emitMOVLLG(b, 18); /* R0 <- sh2[VBR] */
2177
emitMOVLS4(b, R0, regn, R8); /* sh2[Rn] <- R0 */
2178
2179
++b->cycles; /* 1 Cycle */
2180
b->pc += 2;
2181
}
2182
2183
static void generateSTCMSR(uint16_t inst, sh2rec_block_t *b) {
2184
int regn = INSTRUCTION_B(inst);
2185
2186
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
2187
emitMOVLL4(b, R9, 5, R1); /* R1 <- MappedMemoryWriteLong */
2188
emitMOVLL4(b, R8, regn, R4); /* R4 <- sh2[Rn] */
2189
emitSTS(b, R_PR, R10); /* R10 <- PR */
2190
emitADDI(b, -4, R4); /* R4 -= 4 */
2191
emitMOV(b, R0, R5); /* R5 <- R0 */
2192
emitJSR(b, R1); /* Call MappedMemoryWriteLong */
2193
emitMOVLS4(b, R4, regn, R8); /* sh2[Rn] <- R4 */
2194
emitLDS(b, R10, R_PR); /* PR <- R10 */
2195
2196
b->cycles += 2; /* 2 Cycles */
2197
b->pc += 2;
2198
}
2199
2200
static void generateSTCMGBR(uint16_t inst, sh2rec_block_t *b) {
2201
int regn = INSTRUCTION_B(inst);
2202
2203
emitMOVLLG(b, 17); /* R0 <- sh2[GBR] */
2204
emitMOVLL4(b, R9, 5, R1); /* R1 <- MappedMemoryWriteLong */
2205
emitMOVLL4(b, R8, regn, R4); /* R4 <- sh2[Rn] */
2206
emitSTS(b, R_PR, R10); /* R10 <- PR */
2207
emitADDI(b, -4, R4); /* R4 -= 4 */
2208
emitMOV(b, R0, R5); /* R5 <- R0 */
2209
emitJSR(b, R1); /* Call MappedMemoryWriteLong */
2210
emitMOVLS4(b, R4, regn, R8); /* sh2[Rn] <- R4 */
2211
emitLDS(b, R10, R_PR); /* PR <- R10 */
2212
2213
b->cycles += 2; /* 2 Cycles */
2214
b->pc += 2;
2215
}
2216
2217
static void generateSTCMVBR(uint16_t inst, sh2rec_block_t *b) {
2218
int regn = INSTRUCTION_B(inst);
2219
2220
emitMOVLLG(b, 18); /* R0 <- sh2[VBR] */
2221
emitMOVLL4(b, R9, 5, R1); /* R1 <- MappedMemoryWriteLong */
2222
emitMOVLL4(b, R8, regn, R4); /* R4 <- sh2[Rn] */
2223
emitSTS(b, R_PR, R10); /* R10 <- PR */
2224
emitADDI(b, -4, R4); /* R4 -= 4 */
2225
emitMOV(b, R0, R5); /* R5 <- R0 */
2226
emitJSR(b, R1); /* Call MappedMemoryWriteLong */
2227
emitMOVLS4(b, R4, regn, R8); /* sh2[Rn] <- R4 */
2228
emitLDS(b, R10, R_PR); /* PR <- R10 */
2229
2230
b->cycles += 2; /* 2 Cycles */
2231
b->pc += 2;
2232
}
2233
2234
static void generateSTSMACH(uint16_t inst, sh2rec_block_t *b) {
2235
int regn = INSTRUCTION_B(inst);
2236
2237
emitSTS(b, R_MACH, R0); /* R0 <- MACH */
2238
emitMOVLS4(b, R0, regn, R8); /* sh2[Rn] <- R0 */
2239
2240
++b->cycles; /* 1 Cycle */
2241
b->pc += 2;
2242
}
2243
2244
static void generateSTSMACL(uint16_t inst, sh2rec_block_t *b) {
2245
int regn = INSTRUCTION_B(inst);
2246
2247
emitSTS(b, R_MACL, R0); /* R0 <- MACL */
2248
emitMOVLS4(b, R0, regn, R8); /* sh2[Rn] <- R0 */
2249
2250
++b->cycles; /* 1 Cycle */
2251
b->pc += 2;
2252
}
2253
2254
static void generateSTSPR(uint16_t inst, sh2rec_block_t *b) {
2255
int regn = INSTRUCTION_B(inst);
2256
2257
emitMOVLLG(b, 21); /* R0 <- sh2[PR] */
2258
emitMOVLS4(b, R0, regn, R8); /* sh2[Rn] <- R0 */
2259
2260
++b->cycles; /* 1 Cycle */
2261
b->pc += 2;
2262
}
2263
2264
static void generateSTSMMACH(uint16_t inst, sh2rec_block_t *b) {
2265
int regn = INSTRUCTION_B(inst);
2266
2267
emitSTS(b, R_MACH, R5); /* R5 <- MACH */
2268
emitMOVLL4(b, R9, 5, R1); /* R1 <- MappedMemoryWriteLong */
2269
emitMOVLL4(b, R8, regn, R4); /* R4 <- sh2[Rn] */
2270
emitSTS(b, R_PR, R10); /* R10 <- PR */
2271
emitADDI(b, -4, R4); /* R4 -= 4 */
2272
emitJSR(b, R1); /* Call MappedMemoryWriteLong */
2273
emitMOVLS4(b, R4, regn, R8); /* sh2[Rn] <- R4 */
2274
emitLDS(b, R10, R_PR); /* PR <- R10 */
2275
2276
++b->cycles; /* 1 Cycle */
2277
b->pc += 2;
2278
}
2279
2280
static void generateSTSMMACL(uint16_t inst, sh2rec_block_t *b) {
2281
int regn = INSTRUCTION_B(inst);
2282
2283
emitSTS(b, R_MACL, R5); /* R5 <- MACL */
2284
emitMOVLL4(b, R9, 5, R1); /* R1 <- MappedMemoryWriteLong */
2285
emitMOVLL4(b, R8, regn, R4); /* R4 <- sh2[Rn] */
2286
emitSTS(b, R_PR, R10); /* R10 <- PR */
2287
emitADDI(b, -4, R4); /* R4 -= 4 */
2288
emitJSR(b, R1); /* Call MappedMemoryWriteLong */
2289
emitMOVLS4(b, R4, regn, R8); /* sh2[Rn] <- R4 */
2290
emitLDS(b, R10, R_PR); /* PR <- R10 */
2291
2292
++b->cycles; /* 1 Cycle */
2293
b->pc += 2;
2294
}
2295
2296
static void generateSTSMPR(uint16_t inst, sh2rec_block_t *b) {
2297
int regn = INSTRUCTION_B(inst);
2298
2299
emitMOVLLG(b, 21); /* R0 <- sh2[PR] */
2300
emitMOVLL4(b, R9, 5, R1); /* R1 <- MappedMemoryWriteLong */
2301
emitMOVLL4(b, R8, regn, R4); /* R4 <- sh2[Rn] */
2302
emitSTS(b, R_PR, R10); /* R10 <- PR */
2303
emitADDI(b, -4, R4); /* R4 -= 4 */
2304
emitMOV(b, R0, R5); /* R5 <- R0 */
2305
emitJSR(b, R1); /* Call MappedMemoryWriteLong */
2306
emitMOVLS4(b, R4, regn, R8); /* sh2[Rn] <- R4 */
2307
emitLDS(b, R10, R_PR); /* PR <- R10 */
2308
2309
++b->cycles; /* 1 Cycle */
2310
b->pc += 2;
2311
}
2312
2313
static void generateSUB(uint16_t inst, sh2rec_block_t *b) {
2314
generateALUOP(inst, b, OP_SUB);
2315
b->pc += 2;
2316
}
2317
2318
static void generateSUBC(uint16_t inst, sh2rec_block_t *b) {
2319
int regn = INSTRUCTION_B(inst);
2320
int regm = INSTRUCTION_C(inst);
2321
2322
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
2323
emitMOVLL4(b, R8, regn, R2); /* R2 <- sh2[Rn] */
2324
emitMOVLL4(b, R8, regm, R3); /* R3 <- sh2[Rm] */
2325
emitSHIFT(b, R0, OP_ROTCR); /* Rotate SH2's T Bit in place */
2326
emitALU(b, R3, R2, OP_SUBC); /* R2 = R2 - R3 - T (borrow to T) */
2327
emitSHIFT(b, R0, OP_ROTCL); /* Rotate T back to SH2 reg */
2328
emitMOVLS4(b, R2, regn, R8); /* sh2[Rn] <- R2 */
2329
emitMOVLSG(b, 16); /* sh2[SR] <- R0 */
2330
2331
++b->cycles; /* 1 Cycle */
2332
b->pc += 2;
2333
}
2334
2335
static void generateSUBV(uint16_t inst, sh2rec_block_t *b) {
2336
int regn = INSTRUCTION_B(inst);
2337
int regm = INSTRUCTION_C(inst);
2338
2339
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
2340
emitMOVLL4(b, R8, regn, R2); /* R2 <- sh2[Rn] */
2341
emitMOVLL4(b, R8, regm, R3); /* R3 <- sh2[Rm] */
2342
emitSHIFT(b, R0, OP_ROTCR); /* Rotate SH2's T Bit in place */
2343
emitSUBV(b, R3, R2); /* R2 = R2 - R3 (underflow to T Bit) */
2344
emitSHIFT(b, R0, OP_ROTCL); /* Rotate T back to SH2 reg */
2345
emitMOVLSG(b, 16); /* sh2[SR] <- R0 */
2346
2347
++b->cycles; /* 1 Cycle */
2348
b->pc += 2;
2349
}
2350
2351
static void generateSWAPB(uint16_t inst, sh2rec_block_t *b) {
2352
generateALUOP(inst, b, OP_SWAPB);
2353
b->pc += 2;
2354
}
2355
2356
static void generateSWAPW(uint16_t inst, sh2rec_block_t *b) {
2357
generateALUOP(inst, b, OP_SWAPW);
2358
b->pc += 2;
2359
}
2360
2361
static void generateTAS(uint16_t inst, sh2rec_block_t *b) {
2362
int regn = INSTRUCTION_B(inst);
2363
2364
emitMOVLL4(b, R9, 0, R0); /* R0 <- MappedMemoryReadByte */
2365
emitSTS(b, R_PR, R10); /* R10 <- PR */
2366
emitJSR(b, R0); /* Call MappedMemoryReadByte */
2367
emitMOVLL4(b, R8, regn, R4); /* R4 <- sh2[Rn] (delay slot) */
2368
emitMOV(b, R0, R5); /* R5 <- R0 (byte read) */
2369
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
2370
emitMOVI(b, 0x80, R2); /* R2 <- 0x80 */
2371
emitMOVLL4(b, R8, regn, R4); /* R4 <- sh2[Rn] */
2372
emitSHIFT(b, R0, OP_ROTCR); /* Rotate SH2's T Bit in place */
2373
emitALU(b, R5, R5, OP_TST); /* T <- 1 if byte == 0, 0 otherwise */
2374
emitSHIFT(b, R0, OP_ROTCL); /* Rotate T back to SH2 reg */
2375
emitMOVLL4(b, R9, 3, R1); /* R1 <- MappedMemoryWriteByte */
2376
emitMOVLSG(b, 16); /* sh2[SR] <- R0 */
2377
emitJSR(b, R1); /* Call MappedMemoryWriteByte */
2378
emitALU(b, R2, R5, OP_OR); /* R5 <- R5 | 0x80 (delay slot) */
2379
emitLDS(b, R10, R_PR); /* PR <- R10 */
2380
2381
b->cycles += 4; /* 4 Cycles */
2382
b->pc += 2;
2383
}
2384
2385
static void generateTRAPA(uint16_t inst, sh2rec_block_t *b) {
2386
int imm = INSTRUCTION_CD(inst);
2387
int disp = (((uint32_t)(b->ptr)) & 0x03) ? 5 : 6;
2388
uint32_t val = b->pc + 2;
2389
2390
emitSTS(b, R_PR, R10); /* R10 <- PR */
2391
emitMOVLL4(b, R8, 15, R4); /* R4 <- sh2[R15] */
2392
emitMOVLL4(b, R9, 5, R1); /* R1 <- MemoryMappedWriteLong */
2393
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
2394
emitADDI(b, -4, R4); /* R4 <- R4 - 4 */
2395
emitJSR(b, R1); /* Call MemoryMappedWriteLong */
2396
emitMOV(b, R0, R5); /* R5 <- R0 (delay slot) */
2397
emitMOVLL4(b, R8, 15, R4); /* R4 <- sh2[R15] */
2398
emitMOVLL4(b, R9, 5, R1); /* R1 <- MemoryMappedWriteLong */
2399
emitADDI(b, -8, R4); /* R4 <- R4 - 8 */
2400
emitMOVLI(b, disp, R5); /* R5 <- Updated PC value (to be stacked) */
2401
emitJSR(b, R1); /* Call MemoryMappedWriteLong */
2402
emitMOVLS4(b, R4, 15, R8); /* sh2[R15] <- R4 (delay slot) */
2403
emitMOVI(b, imm, R4); /* R4 <- immediate data */
2404
emitALU(b, R4, R4, OP_EXTUB); /* Zero-extend R4 */
2405
emitMOVLL4(b, R9, 2, R1); /* R1 <- MemoryMappedReadLong */
2406
emitMOVLLG(b, 18); /* R0 <- sh2[VBR] */
2407
emitSHLL2(b, R4); /* R4 <- R4 << 2 */
2408
emitJSR(b, R1); /* Call MemoryMappedReadLong */
2409
emitALU(b, R0, R4, OP_ADD); /* R4 <- R4 + R0 (delay slot) */
2410
emitLDS(b, R10, R_PR); /* PR <- R10 */
2411
emitRTS(b); /* Return to sender! */
2412
emitNOP(b); /* XXXX: Nothing here */
2413
if(((uint32_t)b->ptr) & 0x03)
2414
emit16(b, 0); /* Padding for the alignment */
2415
emit32(b, val); /* The PC value to be loaded by the MOVLI */
2416
2417
b->cycles += 8; /* 8 Cycles */
2418
}
2419
2420
static void generateTST(uint16_t inst, sh2rec_block_t *b) {
2421
generateCOMP(inst, b, OP_TST);
2422
b->pc += 2;
2423
}
2424
2425
static void generateTSTI(uint16_t inst, sh2rec_block_t *b) {
2426
int imm = INSTRUCTION_CD(inst);
2427
2428
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
2429
emitMOV(b, R0, R2); /* R2 <- R0 */
2430
emitMOVLL4(b, R8, 0, R0); /* R0 <- sh2[R0] */
2431
emitSHIFT(b, R2, OP_ROTCR); /* Rotate SH2's T Bit in place */
2432
emitTSTI(b, imm); /* tst #imm, r0 */
2433
emitSHIFT(b, R2, OP_ROTCL); /* Rotate T back to SH2 reg */
2434
emitMOV(b, R2, R0); /* R0 <- R2 */
2435
emitMOVLSG(b, 16); /* sh2[SR] <- R0 */
2436
2437
++b->cycles; /* 1 Cycle */
2438
b->pc += 2;
2439
}
2440
2441
static void generateTSTM(uint16_t inst, sh2rec_block_t *b) {
2442
int imm = INSTRUCTION_CD(inst);
2443
2444
emitSTS(b, R_PR, R10); /* R10 <- PR */
2445
emitMOVLL4(b, R9, 0, R1); /* R1 <- MappedMemoryReadByte */
2446
emitMOVLLG(b, 17); /* R0 <- sh2[GBR] */
2447
emitMOVLL4(b, R8, 0, R4); /* R4 <- sh2[R0] */
2448
emitJSR(b, R1); /* Call MappedMemoryReadByte */
2449
emitALU(b, R0, R4, OP_ADD); /* R4 <- R4 + R0 (delay slot) */
2450
emitMOV(b, R0, R5); /* R5 <- R0 (byte read) */
2451
emitMOVI(b, imm, R3); /* R3 <- immediate value */
2452
emitMOVLLG(b, 16); /* R0 <- sh2[SR] */
2453
emitSHIFT(b, R0, OP_ROTCR); /* Rotate SH2's T Bit in place */
2454
emitALU(b, R3, R5, OP_TST); /* T <- 1 if (R5 & imm) == 0, 0 otherwise */
2455
emitSHIFT(b, R0, OP_ROTCL); /* Rotate T back to SH2 reg */
2456
emitMOVLSG(b, 16); /* sh2[SR] <- R0 */
2457
emitLDS(b, R10, R_PR); /* PR <- R10 */
2458
2459
b->cycles += 3; /* 3 Cycles */
2460
b->pc += 2;
2461
}
2462
2463
static void generateXOR(uint16_t inst, sh2rec_block_t *b) {
2464
generateALUOP(inst, b, OP_XOR);
2465
b->pc += 2;
2466
}
2467
2468
static void generateXORI(uint16_t inst, sh2rec_block_t *b) {
2469
int imm = INSTRUCTION_CD(inst);
2470
2471
emitMOVLL4(b, R8, 0, R0); /* R0 <- sh2[R0] */
2472
emitXORI(b, imm); /* R0 <- R0 ^ #imm */
2473
emitMOVLS4(b, R0, 0, R8); /* sh2[R0] <- R0 */
2474
2475
++b->cycles; /* 1 Cycle */
2476
b->pc += 2;
2477
}
2478
2479
static void generateXORM(uint16_t inst, sh2rec_block_t *b) {
2480
int imm = INSTRUCTION_CD(inst);
2481
2482
emitSTS(b, R_PR, R10); /* R10 <- PR */
2483
emitMOVLLG(b, 17); /* R0 <- sh2[GBR] */
2484
emitMOVLL4(b, R8, 0, R4); /* R4 <- sh2[R0] */
2485
emitMOVLL4(b, R9, 0, R1); /* R1 <- MappedMemoryReadByte */
2486
emitALU(b, R0, R4, OP_ADD); /* R4 <- R4 + R0 */
2487
emitJSR(b, R1); /* Call MappedMemoryReadByte */
2488
emitMOVLM(b, R4, R15); /* Push R4 on the stack (delay slot) */
2489
emitMOVLL4(b, R9, 3, R1); /* R1 <- MappedMemoryWriteByte */
2490
emitXORI(b, imm); /* R0 <- R0 ^ #imm */
2491
emitMOVLP(b, R15, R4); /* Pop R4 off the stack */
2492
emitJSR(b, R1); /* Call MappedMemoryWriteByte */
2493
emitMOV(b, R0, R5); /* R5 <- R0 (delay slot) */
2494
emitLDS(b, R10, R_PR); /* PR <- R10 */
2495
2496
b->cycles += 3; /* 3 Cycles */
2497
b->pc += 2;
2498
}
2499
2500
static void generateXTRCT(uint16_t inst, sh2rec_block_t *b) {
2501
generateALUOP(inst, b, OP_XTRCT);
2502
b->pc += 2;
2503
}
2504
2505
int sh2rec_rec_inst(sh2rec_block_t *b, int isdelay) {
2506
uint16_t inst = MappedMemoryReadWord(b->pc);
2507
int done = 0;
2508
2509
switch(INSTRUCTION_A(inst)) {
2510
case 0:
2511
switch(INSTRUCTION_D(inst)) {
2512
case 2:
2513
switch(INSTRUCTION_C(inst)) {
2514
case 0: generateSTCSR(inst, b); break;
2515
case 1: generateSTCGBR(inst, b); break;
2516
case 2: generateSTCVBR(inst, b); break;
2517
default: return -1;
2518
}
2519
break;
2520
2521
case 3:
2522
switch(INSTRUCTION_C(inst)) {
2523
case 0: generateBSRF(inst, b); done = 1; break;
2524
case 2: generateBRAF(inst, b); done = 1; break;
2525
default: return -1;
2526
}
2527
break;
2528
2529
case 4: generateMOVBS0(inst, b); break;
2530
case 5: generateMOVWS0(inst, b); break;
2531
case 6: generateMOVLS0(inst, b); break;
2532
case 7: generateMULL(inst, b); break;
2533
case 8:
2534
switch(INSTRUCTION_C(inst)) {
2535
case 0: generateCLRT(inst, b); break;
2536
case 1: generateSETT(inst, b); break;
2537
case 2: generateCLRMAC(inst, b); break;
2538
default: return -1;
2539
}
2540
break;
2541
2542
case 9:
2543
switch(INSTRUCTION_C(inst)) {
2544
case 0: generateNOP(inst, b); break;
2545
case 1: generateDIV0U(inst, b); break;
2546
case 2: generateMOVT(inst, b); break;
2547
default: return -1;
2548
}
2549
break;
2550
2551
case 10:
2552
switch(INSTRUCTION_C(inst)) {
2553
case 0: generateSTSMACH(inst, b); break;
2554
case 1: generateSTSMACL(inst, b); break;
2555
case 2: generateSTSPR(inst, b); break;
2556
default: return -1;
2557
}
2558
break;
2559
2560
case 11:
2561
switch(INSTRUCTION_C(inst)) {
2562
case 0: generateRTS(inst, b); done = 1; break;
2563
case 1: generateSLEEP(inst, b); break;
2564
case 2: generateRTE(inst, b); done = 1; break;
2565
default: return -1;
2566
}
2567
break;
2568
2569
case 12: generateMOVBL0(inst, b); break;
2570
case 13: generateMOVWL0(inst, b); break;
2571
case 14: generateMOVLL0(inst, b); break;
2572
case 15: generateMACL(inst, b); break;
2573
default: return -1;
2574
}
2575
break;
2576
2577
case 1: generateMOVLS4(inst, b); break;
2578
case 2:
2579
switch(INSTRUCTION_D(inst)) {
2580
case 0: generateMOVBS(inst, b); break;
2581
case 1: generateMOVWS(inst, b); break;
2582
case 2: generateMOVLS(inst, b); break;
2583
case 4: generateMOVBM(inst, b); break;
2584
case 5: generateMOVWM(inst, b); break;
2585
case 6: generateMOVLM(inst, b); break;
2586
case 7: generateDIV0S(inst, b); break;
2587
case 8: generateTST(inst, b); break;
2588
case 9: generateAND(inst, b); break;
2589
case 10: generateXOR(inst, b); break;
2590
case 11: generateOR(inst, b); break;
2591
case 12: generateCMPSTR(inst, b); break;
2592
case 13: generateXTRCT(inst, b); break;
2593
case 14: generateMULU(inst, b); break;
2594
case 15: generateMULS(inst, b); break;
2595
default: return -1;
2596
}
2597
break;
2598
2599
case 3:
2600
switch(INSTRUCTION_D(inst)) {
2601
case 0: generateCMPEQ(inst, b); break;
2602
case 2: generateCMPHS(inst, b); break;
2603
case 3: generateCMPGE(inst, b); break;
2604
case 4: generateDIV1(inst, b); break;
2605
case 5: generateDMULU(inst, b); break;
2606
case 6: generateCMPHI(inst, b); break;
2607
case 7: generateCMPGT(inst, b); break;
2608
case 8: generateSUB(inst, b); break;
2609
case 10: generateSUBC(inst, b); break;
2610
case 11: generateSUBV(inst, b); break;
2611
case 12: generateADD(inst, b); break;
2612
case 13: generateDMULS(inst, b); break;
2613
case 14: generateADDC(inst, b); break;
2614
case 15: generateADDV(inst, b); break;
2615
default: return -1;
2616
}
2617
break;
2618
2619
case 4:
2620
switch(INSTRUCTION_D(inst)) {
2621
case 0:
2622
switch(INSTRUCTION_C(inst)) {
2623
case 0: generateSHLL(inst, b); break;
2624
case 1: generateDT(inst, b); break;
2625
case 2: generateSHAL(inst, b); break;
2626
default: return -1;
2627
}
2628
break;
2629
2630
case 1:
2631
switch(INSTRUCTION_C(inst)) {
2632
case 0: generateSHLR(inst, b); break;
2633
case 1: generateCMPPZ(inst, b); break;
2634
case 2: generateSHAR(inst, b); break;
2635
default: return -1;
2636
}
2637
break;
2638
2639
case 2:
2640
switch(INSTRUCTION_C(inst)) {
2641
case 0: generateSTSMMACH(inst, b); break;
2642
case 1: generateSTSMMACL(inst, b); break;
2643
case 2: generateSTSMPR(inst, b); break;
2644
default: return -1;
2645
}
2646
break;
2647
2648
case 3:
2649
switch(INSTRUCTION_C(inst)) {
2650
case 0: generateSTCMSR(inst, b); break;
2651
case 1: generateSTCMGBR(inst, b); break;
2652
case 2: generateSTCMVBR(inst, b); break;
2653
default: return -1;
2654
}
2655
break;
2656
2657
case 4:
2658
switch(INSTRUCTION_C(inst)) {
2659
case 0: generateROTL(inst, b); break;
2660
case 2: generateROTCL(inst, b); break;
2661
default: return -1;
2662
}
2663
break;
2664
2665
case 5:
2666
switch(INSTRUCTION_C(inst)) {
2667
case 0: generateROTR(inst, b); break;
2668
case 1: generateCMPPL(inst, b); break;
2669
case 2: generateROTCR(inst, b); break;
2670
default: return -1;
2671
}
2672
break;
2673
2674
case 6:
2675
switch(INSTRUCTION_C(inst)) {
2676
case 0: generateLDSMMACH(inst, b); break;
2677
case 1: generateLDSMMACL(inst, b); break;
2678
case 2: generateLDSMPR(inst, b); break;
2679
default: return -1;
2680
}
2681
break;
2682
2683
case 7:
2684
switch(INSTRUCTION_C(inst)) {
2685
case 0: generateLDCMSR(inst, b); break;
2686
case 1: generateLDCMGBR(inst, b); break;
2687
case 2: generateLDCMVBR(inst, b); break;
2688
default: return -1;
2689
}
2690
break;
2691
2692
case 8:
2693
switch(INSTRUCTION_C(inst)) {
2694
case 0: generateSHLL2(inst, b); break;
2695
case 1: generateSHLL8(inst, b); break;
2696
case 2: generateSHLL16(inst, b); break;
2697
default: return -1;
2698
}
2699
break;
2700
2701
case 9:
2702
switch(INSTRUCTION_C(inst)) {
2703
case 0: generateSHLR2(inst, b); break;
2704
case 1: generateSHLR8(inst, b); break;
2705
case 2: generateSHLR16(inst, b); break;
2706
default: return -1;
2707
}
2708
break;
2709
2710
case 10:
2711
switch(INSTRUCTION_C(inst)) {
2712
case 0: generateLDSMACH(inst, b); break;
2713
case 1: generateLDSMACL(inst, b); break;
2714
case 2: generateLDSPR(inst, b); break;
2715
default: return -1;
2716
}
2717
break;
2718
2719
case 11:
2720
switch(INSTRUCTION_C(inst)) {
2721
case 0: generateJSR(inst, b); done = 1; break;
2722
case 1: generateTAS(inst, b); break;
2723
case 2: generateJMP(inst, b); done = 1; break;
2724
default: return -1;
2725
}
2726
break;
2727
2728
case 14:
2729
switch(INSTRUCTION_C(inst)) {
2730
case 0: generateLDCSR(inst, b); break;
2731
case 1: generateLDCGBR(inst, b); break;
2732
case 2: generateLDCVBR(inst, b); break;
2733
default: return -1;
2734
}
2735
break;
2736
2737
case 15: generateMACW(inst, b); break;
2738
default: return -1;
2739
}
2740
break;
2741
2742
case 5: generateMOVLL4(inst, b); break;
2743
2744
case 6:
2745
switch(INSTRUCTION_D(inst)) {
2746
case 0: generateMOVBL(inst, b); break;
2747
case 1: generateMOVWL(inst, b); break;
2748
case 2: generateMOVLL(inst, b); break;
2749
case 3: generateMOV(inst, b); break;
2750
case 4: generateMOVBP(inst, b); break;
2751
case 5: generateMOVWP(inst, b); break;
2752
case 6: generateMOVLP(inst, b); break;
2753
case 7: generateNOT(inst, b); break;
2754
case 8: generateSWAPB(inst, b); break;
2755
case 9: generateSWAPW(inst, b); break;
2756
case 10: generateNEGC(inst, b); break;
2757
case 11: generateNEG(inst, b); break;
2758
case 12: generateEXTUB(inst, b); break;
2759
case 13: generateEXTUW(inst, b); break;
2760
case 14: generateEXTSB(inst, b); break;
2761
case 15: generateEXTSW(inst, b); break;
2762
}
2763
break;
2764
2765
case 7: generateADDI(inst, b); break;
2766
2767
case 8:
2768
switch(INSTRUCTION_B(inst)) {
2769
case 0: generateMOVBS4(inst, b); break;
2770
case 1: generateMOVWS4(inst, b); break;
2771
case 4: generateMOVBL4(inst, b); break;
2772
case 5: generateMOVWL4(inst, b); break;
2773
case 8: generateCMPIM(inst, b); break;
2774
case 9: generateBT(inst, b); done = 1; break;
2775
case 11: generateBF(inst, b); done = 1; break;
2776
case 13: generateBTS(inst, b); done = 1; break;
2777
case 15: generateBFS(inst, b); done = 1; break;
2778
default: return -1;
2779
}
2780
break;
2781
2782
case 9: generateMOVWI(inst, b); break;
2783
case 10: generateBRA(inst, b); done = 1; break;
2784
case 11: generateBSR(inst, b); done = 1; break;
2785
2786
case 12:
2787
switch(INSTRUCTION_B(inst)) {
2788
case 0: generateMOVBSG(inst, b); break;
2789
case 1: generateMOVWSG(inst, b); break;
2790
case 2: generateMOVLSG(inst, b); break;
2791
case 3: generateTRAPA(inst, b); done = 1; break;
2792
case 4: generateMOVBLG(inst, b); break;
2793
case 5: generateMOVWLG(inst, b); break;
2794
case 6: generateMOVLLG(inst, b); break;
2795
case 7: generateMOVA(inst, b); break;
2796
case 8: generateTSTI(inst, b); break;
2797
case 9: generateANDI(inst, b); break;
2798
case 10: generateXORI(inst, b); break;
2799
case 11: generateORI(inst, b); break;
2800
case 12: generateTSTM(inst, b); break;
2801
case 13: generateANDM(inst, b); break;
2802
case 14: generateXORM(inst, b); break;
2803
case 15: generateORM(inst, b); break;
2804
}
2805
break;
2806
2807
case 13: generateMOVLI(inst, b); break;
2808
case 14: generateMOVI(inst, b); break;
2809
default: return -1;
2810
}
2811
2812
return done;
2813
}
2814
2815
int sh2rec_rec_block(sh2rec_block_t *b) {
2816
int done = 0;
2817
2818
while(!done) {
2819
done = sh2rec_rec_inst(b, 0);
2820
}
2821
2822
/* Flush the icache, so we don't execute stale data */
2823
icache_flush_range((uint32)b->block, ((u32)b->ptr) - ((u32)b->block));
2824
2825
return 0;
2826
}
2827
2828
/* In sh2exec.s */
2829
extern void sh2rec_exec(SH2_struct *cxt, u32 cycles);
2830
2831
static int sh2rec_init(void) {
2832
/* Initialize anything important here */
2833
sh2rec_htab_init();
2834
return 0;
2835
}
2836
2837
static void sh2rec_deinit(void) {
2838
/* Clean stuff up here */
2839
sh2rec_htab_reset();
2840
}
2841
2842
static void sh2rec_reset(void) {
2843
/* Reset to a sane state */
2844
sh2rec_htab_reset();
2845
}
2846
2847
/* This function borrowed from the interpreter core */
2848
void sh2rec_check_interrupts(SH2_struct *c) {
2849
if(c->NumberOfInterrupts != 0) {
2850
if(c->interrupts[c->NumberOfInterrupts-1].level > c->regs.SR.part.I) {
2851
c->regs.R[15] -= 4;
2852
MappedMemoryWriteLong(c->regs.R[15], c->regs.SR.all);
2853
c->regs.R[15] -= 4;
2854
MappedMemoryWriteLong(c->regs.R[15], c->regs.PC);
2855
c->regs.SR.part.I = c->interrupts[c->NumberOfInterrupts - 1].level;
2856
c->regs.PC = MappedMemoryReadLong(c->regs.VBR + (c->interrupts[c->NumberOfInterrupts-1].vector << 2));
2857
c->NumberOfInterrupts--;
2858
c->isSleeping = 0;
2859
}
2860
}
2861
}
2862
2863
sh2rec_block_t *sh2rec_find_block(u32 pc) {
2864
sh2rec_block_t *b = sh2rec_htab_lookup(pc);
2865
2866
if(!b) {
2867
b = sh2rec_htab_block_create(pc, 4096);
2868
sh2rec_rec_block(b);
2869
}
2870
2871
return b;
2872
}
2873
2874
SH2Interface_struct SH2Dynarec = {
2875
SH2CORE_DYNAREC,
2876
"SH2 -> SH4 Dynarec",
2877
2878
sh2rec_init, /* Init */
2879
sh2rec_deinit, /* DeInit */
2880
sh2rec_reset, /* Reset */
2881
sh2rec_exec, /* Exec */
2882
2883
SH2InterpreterGetRegisters, /* GetRegisters */
2884
SH2InterpreterGetGPR, /* GetGPR */
2885
SH2InterpreterGetSR, /* GetSR */
2886
SH2InterpreterGetGBR, /* GetGBR */
2887
SH2InterpreterGetVBR, /* GetVBR */
2888
SH2InterpreterGetMACH, /* GetMACH */
2889
SH2InterpreterGetMACL, /* GetMACL */
2890
SH2InterpreterGetPR, /* GetPR */
2891
SH2InterpreterGetPC, /* GetPC */
2892
2893
SH2InterpreterSetRegisters, /* SetRegisters */
2894
SH2InterpreterSetGPR, /* SetGPR */
2895
SH2InterpreterSetSR, /* SetSR */
2896
SH2InterpreterSetGBR, /* SetGBR */
2897
SH2InterpreterSetVBR, /* SetVBR */
2898
SH2InterpreterSetMACH, /* SetMACH */
2899
SH2InterpreterSetMACL, /* SetMACL */
2900
SH2InterpreterSetPR, /* SetPR */
2901
SH2InterpreterSetPC, /* SetPC */
2902
2903
SH2InterpreterSendInterrupt, /* SendInterrupt */
2904
SH2InterpreterGetInterrupts, /* GetInterrupts */
2905
SH2InterpreterSetInterrupts, /* SetInterrupts */
2906
2907
NULL /* WriteNotify */
2908
};
2909
2910