44 #ifdef GATHER_BDT_STATISTICS
60 static void update_bdt_statistics(uint32_t iw)
62 static FILE *
f = NULL;
63 static long long *counts;
64 static char *counts_used;
65 static long long n = 0;
68 size_t s = (1 << 24) *
sizeof(
long long);
69 f = fopen(
"bdt_statistics.txt",
"w");
71 fprintf(stderr,
"update_bdt_statistics(): :-(\n");
79 iw = ((iw & 0x01800000) >> 1) | (iw & 0x003fffff);
81 counts_used[iw & 0xffff] = 1;
85 if ((n % 500000) == 0) {
88 fatal(
"[ update_bdt_statistics(): n = %lli ]\n", (
long long) n);
89 fseek(
f, 0, SEEK_SET);
90 for (i=0; i<0x1000000; i++)
91 if (counts_used[i & 0xffff] && counts[i] != 0) {
93 uint32_t opcode = ((i & 0x00c00000) << 1)
94 | (i & 0x003fffff) | 0x08000000;
95 for (j=0; j<counts[i]; j++)
96 fprintf(
f,
"0x%08x\n", opcode);
128 uint8_t
condition_hi[16] = { 0,0,1,1, 0,0,0,0, 0,0,1,1, 0,0,0,0 };
129 uint8_t
condition_ge[16] = { 1,0,1,0, 1,0,1,0, 0,1,0,1, 0,1,0,1 };
130 uint8_t
condition_gt[16] = { 1,0,1,0, 0,0,0,0, 0,1,0,1, 0,0,0,0 };
132 #define Y(n) void arm_instr_ ## n ## __eq(struct cpu *cpu, \
133 struct arm_instr_call *ic) \
134 { if (cpu->cd.arm.flags & ARM_F_Z) \
135 arm_instr_ ## n (cpu, ic); } \
136 void arm_instr_ ## n ## __ne(struct cpu *cpu, \
137 struct arm_instr_call *ic) \
138 { if (!(cpu->cd.arm.flags & ARM_F_Z)) \
139 arm_instr_ ## n (cpu, ic); } \
140 void arm_instr_ ## n ## __cs(struct cpu *cpu, \
141 struct arm_instr_call *ic) \
142 { if (cpu->cd.arm.flags & ARM_F_C) \
143 arm_instr_ ## n (cpu, ic); } \
144 void arm_instr_ ## n ## __cc(struct cpu *cpu, \
145 struct arm_instr_call *ic) \
146 { if (!(cpu->cd.arm.flags & ARM_F_C)) \
147 arm_instr_ ## n (cpu, ic); } \
148 void arm_instr_ ## n ## __mi(struct cpu *cpu, \
149 struct arm_instr_call *ic) \
150 { if (cpu->cd.arm.flags & ARM_F_N) \
151 arm_instr_ ## n (cpu, ic); } \
152 void arm_instr_ ## n ## __pl(struct cpu *cpu, \
153 struct arm_instr_call *ic) \
154 { if (!(cpu->cd.arm.flags & ARM_F_N)) \
155 arm_instr_ ## n (cpu, ic); } \
156 void arm_instr_ ## n ## __vs(struct cpu *cpu, \
157 struct arm_instr_call *ic) \
158 { if (cpu->cd.arm.flags & ARM_F_V) \
159 arm_instr_ ## n (cpu, ic); } \
160 void arm_instr_ ## n ## __vc(struct cpu *cpu, \
161 struct arm_instr_call *ic) \
162 { if (!(cpu->cd.arm.flags & ARM_F_V)) \
163 arm_instr_ ## n (cpu, ic); } \
164 void arm_instr_ ## n ## __hi(struct cpu *cpu, \
165 struct arm_instr_call *ic) \
166 { if (condition_hi[cpu->cd.arm.flags]) \
167 arm_instr_ ## n (cpu, ic); } \
168 void arm_instr_ ## n ## __ls(struct cpu *cpu, \
169 struct arm_instr_call *ic) \
170 { if (!condition_hi[cpu->cd.arm.flags]) \
171 arm_instr_ ## n (cpu, ic); } \
172 void arm_instr_ ## n ## __ge(struct cpu *cpu, \
173 struct arm_instr_call *ic) \
174 { if (condition_ge[cpu->cd.arm.flags]) \
175 arm_instr_ ## n (cpu, ic); } \
176 void arm_instr_ ## n ## __lt(struct cpu *cpu, \
177 struct arm_instr_call *ic) \
178 { if (!condition_ge[cpu->cd.arm.flags]) \
179 arm_instr_ ## n (cpu, ic); } \
180 void arm_instr_ ## n ## __gt(struct cpu *cpu, \
181 struct arm_instr_call *ic) \
182 { if (condition_gt[cpu->cd.arm.flags]) \
183 arm_instr_ ## n (cpu, ic); } \
184 void arm_instr_ ## n ## __le(struct cpu *cpu, \
185 struct arm_instr_call *ic) \
186 { if (!condition_gt[cpu->cd.arm.flags]) \
187 arm_instr_ ## n (cpu, ic); } \
188 void (*arm_cond_instr_ ## n [16])(struct cpu *, \
189 struct arm_instr_call *) = { \
190 arm_instr_ ## n ## __eq, arm_instr_ ## n ## __ne, \
191 arm_instr_ ## n ## __cs, arm_instr_ ## n ## __cc, \
192 arm_instr_ ## n ## __mi, arm_instr_ ## n ## __pl, \
193 arm_instr_ ## n ## __vs, arm_instr_ ## n ## __vc, \
194 arm_instr_ ## n ## __hi, arm_instr_ ## n ## __ls, \
195 arm_instr_ ## n ## __ge, arm_instr_ ## n ## __lt, \
196 arm_instr_ ## n ## __gt, arm_instr_ ## n ## __le, \
197 arm_instr_ ## n , arm_instr_never };
199 #define cond_instr(n) ( arm_cond_instr_ ## n [condition_code] )
210 low_pc = ((size_t)
ic - (
size_t)
211 cpu->
cd.
arm.cur_ic_page) /
sizeof(
struct arm_instr_call);
216 fatal(
"FATAL ERROR: An internal error occured in the ARM"
217 " dyntrans code. Please contact the author with detailed"
218 " repro steps on how to trigger this bug. pc = 0x%08" PRIx32
"\n",
221 cpu->
cd.
arm.next_ic = ¬hing_call;
231 low_pc = ((size_t)
ic - (
size_t)
232 cpu->
cd.
arm.cur_ic_page) /
sizeof(
struct arm_instr_call);
237 fatal(
"[ ARM: unimplemented 0xf instruction at pc = 0x%08" PRIx32
" ]\n", (uint32_t)
cpu->
pc);
239 cpu->
cd.
arm.next_ic = ¬hing_call;
258 cpu->
pc = (uint32_t)((
cpu->
pc & 0xfffff000) + (int32_t)
ic->arg[0]);
261 quick_pc_to_pointers_arm(
cpu);
275 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
ic->arg[0];
278 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
282 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
286 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
290 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
294 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
298 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
302 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
306 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
311 (
struct arm_instr_call *)
ic->arg[0] :
312 (
struct arm_instr_call *)
ic->arg[1];
315 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
320 (
struct arm_instr_call *)
ic->arg[0] :
321 (
struct arm_instr_call *)
ic->arg[1];
324 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
329 (
struct arm_instr_call *)
ic->arg[0] :
330 (
struct arm_instr_call *)
ic->arg[1];
333 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
337 struct arm_instr_call *) = {
338 arm_instr_b_samepage__eq, arm_instr_b_samepage__ne,
339 arm_instr_b_samepage__cs, arm_instr_b_samepage__cc,
340 arm_instr_b_samepage__mi, arm_instr_b_samepage__pl,
341 arm_instr_b_samepage__vs, arm_instr_b_samepage__vc,
342 arm_instr_b_samepage__hi, arm_instr_b_samepage__ls,
343 arm_instr_b_samepage__ge, arm_instr_b_samepage__lt,
344 arm_instr_b_samepage__gt, arm_instr_b_samepage__le,
363 cpu->
cd.
arm.next_ic = ¬hing_call;
366 fatal(
"[ ARM pc misaligned? 0x%08x ]\n", (
int)
cpu->
pc);
369 cpu->
cd.
arm.next_ic = ¬hing_call;
374 quick_pc_to_pointers_arm(
cpu);
394 cpu->
cd.
arm.next_ic = ¬hing_call;
397 fatal(
"[ ARM pc misaligned? 0x%08x ]\n", (
int)
cpu->
pc);
400 cpu->
cd.
arm.next_ic = ¬hing_call;
407 quick_pc_to_pointers_arm(
cpu);
420 uint32_t pc = ((uint32_t)
cpu->
pc & 0xfffff000) + (int32_t)
ic->arg[1];
424 cpu->
pc = pc + (int32_t)
ic->arg[0];
427 quick_pc_to_pointers_arm(
cpu);
440 uint32_t pc = ((uint32_t)
cpu->
pc & 0xfffff000) + (int32_t)
ic->arg[1];
445 cpu->
pc = pc + (int32_t)
ic->arg[0];
450 fatal(
"[ blx_imm internal error. Should have switched to THUMB! 0x%08x ]\n", (
int)
cpu->
pc);
453 cpu->
cd.
arm.next_ic = ¬hing_call;
458 cpu->
cd.
arm.next_ic = ¬hing_call;
461 fatal(
"[ ARM pc misaligned? 0x%08x ]\n", (
int)
cpu->
pc);
464 cpu->
cd.
arm.next_ic = ¬hing_call;
472 quick_pc_to_pointers_arm(
cpu);
484 uint32_t lr = ((uint32_t)
cpu->
pc & 0xfffff000) + (int32_t)
ic->arg[2];
495 cpu->
cd.
arm.next_ic = ¬hing_call;
498 fatal(
"[ ARM pc misaligned? 0x%08x ]\n", (
int)
cpu->
pc);
501 cpu->
cd.
arm.next_ic = ¬hing_call;
506 quick_pc_to_pointers_arm(
cpu);
518 uint32_t pc = ((uint32_t)
cpu->
pc & 0xfffff000) + (int32_t)
ic->arg[1];
522 cpu->
pc = pc + (int32_t)
ic->arg[0];
527 quick_pc_to_pointers_arm(
cpu);
540 ((uint32_t)
cpu->
pc & 0xfffff000) + (int32_t)
ic->arg[2];
541 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
ic->arg[0];
553 uint32_t low_pc, lr = (
cpu->
pc & 0xfffff000) +
ic->arg[2];
557 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
ic->arg[0];
560 low_pc = ((size_t)
cpu->
cd.
arm.next_ic - (
size_t)
561 cpu->
cd.
arm.cur_ic_page) /
sizeof(
struct arm_instr_call);
580 uint32_t rm =
reg(
ic->arg[0]);
581 int i = 32, n = 0, j;
583 if (rm & 0xff000000) {
584 for (j=0; j<8; j++) {
621 if (result & 0x80000000)
623 reg(
ic->arg[0]) = result;
636 uint32_t iw =
ic->arg[0];
638 rd = (iw >> 16) & 15; rn = (iw >> 12) & 15,
639 rs = (iw >> 8) & 15; rm = iw & 15;
647 uint32_t iw =
ic->arg[0];
649 rd = (iw >> 16) & 15; rn = (iw >> 12) & 15,
650 rs = (iw >> 8) & 15; rm = iw & 15;
670 uint32_t iw; uint64_t tmp;
int u_bit, a_bit;
672 u_bit = iw & 0x00400000; a_bit = iw & 0x00200000;
675 tmp = (int64_t)(int32_t)tmp
676 * (int64_t)(int32_t)
cpu->
cd.
arm.
r[(iw >> 8) & 15];
678 tmp *= (uint64_t)
cpu->
cd.
arm.
r[(iw >> 8) & 15];
680 uint64_t x = ((uint64_t)
cpu->
cd.
arm.
r[(iw >> 16) & 15] << 32)
683 cpu->
cd.
arm.
r[(iw >> 16) & 15] = (x >> 32);
686 cpu->
cd.
arm.
r[(iw >> 16) & 15] = (tmp >> 32);
702 reg(
ic->arg[2]) = (int32_t)(int16_t)
reg(
ic->arg[0]) *
703 (int32_t)(int16_t)
reg(
ic->arg[1]);
708 reg(
ic->arg[2]) = (int32_t)(int16_t)(
reg(
ic->arg[0]) >> 16) *
709 (int32_t)(int16_t)
reg(
ic->arg[1]);
714 reg(
ic->arg[2]) = (int32_t)(int16_t)
reg(
ic->arg[0]) *
715 (int32_t)(int16_t)(
reg(
ic->arg[1]) >> 16);
720 reg(
ic->arg[2]) = (int32_t)(int16_t)(
reg(
ic->arg[0]) >> 16) *
721 (int32_t)(int16_t)(
reg(
ic->arg[1]) >> 16);
747 reg(
ic->arg[1]) = ((uint32_t)
cpu->
pc&0xfffff000) + (int32_t)
ic->arg[0];
760 uint32_t old_pc, mask_within_page;
775 if ((old_pc & ~mask_within_page) == (
cpu->
pc & ~mask_within_page)) {
780 quick_pc_to_pointers_arm(
cpu);
787 quick_pc_to_pointers_arm(
cpu);
804 uint32_t mask =
ic->arg[1];
813 uint32_t new_value =
ic->arg[0];
818 if (switch_register_banks)
826 if (switch_register_banks)
838 uint32_t mask =
ic->arg[1];
839 uint32_t new_value =
ic->arg[0];
861 default:
fatal(
"msr_spsr: unimplemented mode %i\n",
865 uint32_t old_pc, low_pc = ((size_t)
ic - (
size_t)
866 cpu->
cd.
arm.cur_ic_page) /
sizeof(
struct arm_instr_call);
870 printf(
"msr_spsr: old pc = 0x%08" PRIx32
"\n", old_pc);
913 default:
fatal(
"mrs_spsr: unimplemented mode %i\n",
928 uint32_t low_pc = ((size_t)
ic - (
size_t)
929 cpu->
cd.
arm.cur_ic_page) /
sizeof(
struct arm_instr_call);
936 uint32_t low_pc = ((size_t)
ic - (
size_t)
937 cpu->
cd.
arm.cur_ic_page) /
sizeof(
struct arm_instr_call);
955 quick_pc_to_pointers_arm(
cpu);
966 cpu->
cd.
arm.next_ic = ¬hing_call;
976 cpu->
pc &= 0xfffff000;
989 cpu->
pc &= 0xfffff000;
1002 cpu->
pc &= 0xfffff000;
1022 uint32_t low_pc = ((size_t)
ic - (
size_t)
1023 cpu->
cd.
arm.cur_ic_page) /
sizeof(
struct arm_instr_call);
1029 fatal(
"swp: load failed\n");
1032 data = d[0] + (d[1] << 8) + (d[2] << 16) + (d[3] << 24);
1033 data2 =
reg(
ic->arg[1]);
1034 d[0] = data2; d[1] = data2 >> 8; d[2] = data2 >> 16; d[3] = data2 >> 24;
1037 fatal(
"swp: store failed\n");
1049 uint32_t low_pc = ((size_t)
ic - (
size_t)
1050 cpu->
cd.
arm.cur_ic_page) /
sizeof(
struct arm_instr_call);
1056 fatal(
"swp: load failed\n");
1060 d[0] =
reg(
ic->arg[1]);
1063 fatal(
"swp: store failed\n");
1072 struct arm_instr_call *);
1073 X(store_w1_word_u1_p0_imm);
1074 X(store_w0_byte_u1_p0_imm);
1075 X(store_w0_word_u1_p0_imm);
1076 X(store_w0_word_u1_p1_imm);
1077 X(load_w0_word_u1_p0_imm);
1078 X(load_w0_word_u1_p1_imm);
1079 X(load_w1_word_u1_p0_imm);
1080 X(load_w0_byte_u1_p1_imm);
1081 X(load_w0_byte_u1_p1_reg);
1082 X(load_w1_byte_u1_p1_imm);
1085 struct arm_instr_call *);
1088 struct arm_instr_call *);
1091 struct arm_instr_call *);
1093 extern uint32_t (*
arm_r[8192])(
struct cpu *,
struct arm_instr_call *);
1097 struct arm_instr_call *);
1099 struct arm_instr_call *);
1116 void arm_pop(
struct cpu*
cpu, uint32_t* np,
int p_bit,
int u_bit,
int s_bit,
int w_bit, uint32_t iw)
1118 uint32_t
addr = *np;
1119 unsigned char data[4];
1120 unsigned char *
page;
1121 int i, return_flag = 0;
1122 uint32_t new_values[16];
1127 fatal(
"[ bdt_load: s-bit: in usermode? ]\n");
1136 for (i=(u_bit? 0 : 15); i>=0 && i<=15; i+=(u_bit? 1 : -1)) {
1139 if (!((iw >> i) & 1)) {
1146 addr +=
sizeof(uint32_t);
1148 addr -=
sizeof(uint32_t);
1153 uint32_t *p32 = (uint32_t *)
page;
1154 value = p32[(
addr & 0xfff) >> 2];
1157 #ifdef HOST_LITTLE_ENDIAN
1162 value = ((value & 0xff) << 24) |
1163 ((value & 0xff00) << 8) |
1164 ((value & 0xff0000) >> 8) |
1165 ((value & 0xff000000) >> 24);
1183 new_values[i] = value;
1187 addr +=
sizeof(uint32_t);
1189 addr -=
sizeof(uint32_t);
1193 for (i=(u_bit? 0 : 15); i>=0 && i<=15; i+=(u_bit? 1 : -1)) {
1194 if (!((iw >> i) & 1)) {
1208 if (i >= 8 && i <= 14)
1218 if (i >= 13 && i <= 14)
1233 int switch_register_banks;
1246 default:
fatal(
"bdt_load: unimplemented mode %i\n",
1254 if (switch_register_banks)
1260 if (switch_register_banks)
1274 quick_pc_to_pointers_arm(
cpu);
1282 void arm_push(
struct cpu*
cpu, uint32_t* np,
int p_bit,
int u_bit,
int s_bit,
int w_bit, uint16_t regs)
1285 uint32_t value,
addr = *np;
1286 unsigned char data[4];
1287 unsigned char *
page;
1289 for (i=(u_bit? 0 : 15); i>=0 && i<=15; i+=(u_bit? 1 : -1)) {
1290 if (!((regs >> i) & 1)) {
1300 if (i >= 8 && i <= 14)
1307 if (i >= 13 && i <= 14)
1318 value =
cpu->
pc + 12;
1322 addr +=
sizeof(uint32_t);
1324 addr -=
sizeof(uint32_t);
1329 uint32_t *p32 = (uint32_t *)
page;
1332 #ifdef HOST_LITTLE_ENDIAN
1337 value = ((value & 0xff) << 24) |
1338 ((value & 0xff00) << 8) |
1339 ((value & 0xff0000) >> 8) |
1340 ((value & 0xff000000) >> 24);
1341 p32[(
addr & 0xfff) >> 2] = value;
1345 data[1] = value >> 8;
1346 data[2] = value >> 16;
1347 data[3] = value >> 24;
1349 data[0] = value >> 24;
1350 data[1] = value >> 16;
1351 data[2] = value >> 8;
1363 addr +=
sizeof(uint32_t);
1365 addr -=
sizeof(uint32_t);
1382 uint32_t *np = (uint32_t *)
ic->arg[0];
1384 uint32_t iw =
ic->arg[1];
1385 int p_bit = iw & 0x01000000;
1386 int u_bit = iw & 0x00800000;
1387 int s_bit = iw & 0x00400000;
1388 int w_bit = iw & 0x00200000;
1390 #ifdef GATHER_BDT_STATISTICS
1392 update_bdt_statistics(iw);
1396 low_pc = ((size_t)
ic - (
size_t)
1397 cpu->
cd.
arm.cur_ic_page) /
sizeof(
struct arm_instr_call);
1401 arm_pop(
cpu, np, p_bit, u_bit, s_bit, w_bit, (uint16_t)iw);
1414 uint32_t *np = (uint32_t *)
ic->arg[0];
1416 uint32_t iw =
ic->arg[1];
1417 int p_bit = iw & 0x01000000;
1418 int u_bit = iw & 0x00800000;
1419 int s_bit = iw & 0x00400000;
1420 int w_bit = iw & 0x00200000;
1422 #ifdef GATHER_BDT_STATISTICS
1424 update_bdt_statistics(iw);
1428 low_pc = ((size_t)
ic - (
size_t)
1429 cpu->
cd.
arm.cur_ic_page) /
sizeof(
struct arm_instr_call);
1433 arm_push(
cpu, np, p_bit, u_bit, s_bit, w_bit, (uint16_t)iw);
1441 X(multi_0x08b15018);
1442 X(multi_0x08ac000c__ge);
1443 X(multi_0x08a05018);
1461 unsigned char *
page;
1478 if ((
addr & 0xfff) + 128 > 0x1000)
1493 memset(
page + (
addr & 0xfff), 0, 128);
1522 unsigned char *page_0, *page_1;
1523 uint32_t addr_r0, addr_r1;
1532 if ((addr_r0 & 0xfff) + 32 > 0x1000 ||
1533 (addr_r1 & 0xfff) + 32 > 0x1000) {
1538 page_0 =
cpu->
cd.
arm.host_store[addr_r0 >> 12];
1539 page_1 =
cpu->
cd.
arm.host_store[addr_r1 >> 12];
1542 if (page_0 == NULL || page_1 == NULL) {
1547 memcpy(page_0 + (addr_r0 & 0xfff),
1548 page_1 + (addr_r1 & 0xfff), 32);
1657 uint32_t rY =
reg(
ic[0].arg[0]);
1658 uint32_t rZ =
reg(
ic[3].arg[0]);
1662 p = (uint32_t *)
cpu->
cd.
arm.host_load[rY >> 12];
1668 rX = p[(rY & 0xfff) >> 2];
1682 uint32_t low_pc = ((size_t)
ic - (
size_t)
1683 cpu->
cd.
arm.cur_ic_page) /
sizeof(
struct arm_instr_call);
1696 cpu->
cd.
arm.next_ic = ¬hing_call;
1713 unsigned int n_loops = 0;
1714 uint32_t rY, rX =
reg(
ic[0].arg[0]);
1719 p =
cpu->
cd.
arm.host_load[rX >> 12];
1726 rY =
reg(
ic[0].arg[2]) = p[rX & 0xfff];
1727 reg(
ic[0].arg[0]) = rX;
1750 uint32_t tmp =
reg(
ic[0].arg[0]);
1754 reg(
ic[1].arg[0]) = tmp;
1770 uint32_t r0 =
cpu->
cd.
arm.
r[0], ofs = (r0 & 0xffc), index = r0 >> 12;
1771 unsigned char *p =
cpu->
cd.
arm.host_load[index];
1772 uint32_t *p32 = (uint32_t *) p, *q32;
1775 if (ofs > 0x1000 - 6*4 || !ok || p == NULL) {
1781 q32[0] = p32[ofs+2];
1782 q32[1] = p32[ofs+3];
1783 q32[2] = p32[ofs+4];
1784 q32[3] = p32[ofs+5];
1785 q32[4] = p32[ofs+0];
1786 q32[5] = p32[ofs+1];
1805 uint32_t r1 =
cpu->
cd.
arm.
r[1], ofs = (r1 & 0xffc), index = r1 >> 12;
1806 unsigned char *p =
cpu->
cd.
arm.host_store[index];
1807 uint32_t *p32 = (uint32_t *) p, *q32;
1810 if (ofs > 0x1000 - 6*4 || !ok || p == NULL) {
1817 p32[ofs+1] = q32[3];
1818 p32[ofs+2] = q32[4];
1819 p32[ofs+3] = q32[5];
1820 p32[ofs+4] = q32[0];
1821 p32[ofs+5] = q32[1];
1831 X(cmps0_beq_samepage)
1833 uint32_t a =
reg(
ic->arg[0]);
1842 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
ic[1].arg[0];
1851 X(cmps_beq_samepage)
1853 uint32_t a =
reg(
ic->arg[0]), b =
ic->arg[1], c = a - b;
1856 if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1857 ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1861 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
ic[1].arg[0];
1875 uint32_t a =
reg(
ic->arg[0]);
1879 cpu->
pc = (uint32_t)(((uint32_t)
cpu->
pc & 0xfffff000)
1880 + (int32_t)
ic[1].arg[0]);
1881 quick_pc_to_pointers_arm(
cpu);
1890 uint32_t a =
reg(
ic->arg[0]), b =
ic->arg[1], c = a - b;
1893 if ((int32_t)a < 0 && (int32_t)c >= 0)
1897 cpu->
pc = (uint32_t)(((uint32_t)
cpu->
pc & 0xfffff000)
1898 + (int32_t)
ic[1].arg[0]);
1899 quick_pc_to_pointers_arm(
cpu);
1908 uint32_t a =
reg(
ic->arg[0]), b =
ic->arg[1], c = a - b;
1911 if ((int32_t)a >= 0 && (int32_t)c < 0)
1915 cpu->
pc = (uint32_t)(((uint32_t)
cpu->
pc & 0xfffff000)
1916 + (int32_t)
ic[1].arg[0]);
1917 quick_pc_to_pointers_arm(
cpu);
1929 X(cmps0_bne_samepage)
1931 uint32_t a =
reg(
ic->arg[0]);
1942 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
ic[1].arg[0];
1949 X(cmps_bne_samepage)
1951 uint32_t a =
reg(
ic->arg[0]), b =
ic->arg[1], c = a - b;
1954 if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1955 ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1963 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
ic[1].arg[0];
1971 X(cmps_bcc_samepage)
1973 uint32_t a =
reg(
ic->arg[0]), b =
ic->arg[1], c = a - b;
1980 if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
1981 ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
1986 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
ic[1].arg[0];
1993 X(cmps_reg_bcc_samepage)
1995 uint32_t a =
reg(
ic->arg[0]), b =
reg(
ic->arg[1]), c = a - b;
2002 if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
2003 ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
2008 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
ic[1].arg[0];
2015 X(cmps_bhi_samepage)
2017 uint32_t a =
reg(
ic->arg[0]), b =
ic->arg[1], c = a - b;
2024 if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
2025 ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
2028 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
ic[1].arg[0];
2037 X(cmps_reg_bhi_samepage)
2039 uint32_t a =
reg(
ic->arg[0]), b =
reg(
ic->arg[1]), c = a - b;
2046 if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
2047 ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
2050 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
ic[1].arg[0];
2059 X(cmps_bgt_samepage)
2061 uint32_t a =
reg(
ic->arg[0]), b =
ic->arg[1], c = a - b;
2068 if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
2069 ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
2071 if ((int32_t)a > (int32_t)b)
2072 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
ic[1].arg[0];
2081 X(cmps_ble_samepage)
2083 uint32_t a =
reg(
ic->arg[0]), b =
ic->arg[1], c = a - b;
2090 if (((int32_t)a >= 0 && (int32_t)b < 0 && (int32_t)c < 0) ||
2091 ((int32_t)a < 0 && (int32_t)b >= 0 && (int32_t)c >= 0))
2093 if ((int32_t)a <= (int32_t)b)
2094 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
ic[1].arg[0];
2103 X(teqs_beq_samepage)
2105 uint32_t a =
reg(
ic->arg[0]), b =
ic->arg[1], c = a ^ b;
2110 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
2124 X(tsts_lo_beq_samepage)
2126 uint32_t a =
reg(
ic->arg[0]), b =
ic->arg[1], c = a & b;
2132 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
2142 X(teqs_bne_samepage)
2144 uint32_t a =
reg(
ic->arg[0]), b =
ic->arg[1], c = a ^ b;
2156 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
2165 X(tsts_lo_bne_samepage)
2167 uint32_t a =
reg(
ic->arg[0]), b =
ic->arg[1], c = a & b;
2175 cpu->
cd.
arm.next_ic = (
struct arm_instr_call *)
2190 quick_pc_to_pointers_arm(
cpu);
2207 struct arm_instr_call *
ic,
int low_addr)
2209 #ifdef HOST_LITTLE_ENDIAN
2215 for (i=-16; i<=-1; i++)
2216 if (
ic[i].
f !=
instr(multi_0x08ac000c__ge))
2219 ic[-17].arg[0]==
ic[-17].arg[2] &&
ic[-17].arg[1] == 128 &&
2220 ic[ 0].f ==
instr(b_samepage__gt) &&
2221 ic[ 0].arg[0] == (size_t)&
ic[-17]) {
2238 #ifdef HOST_LITTLE_ENDIAN
2243 if (
ic[-5].
f==
instr(multi_0x08b15018) &&
2244 ic[-4].f==
instr(multi_0x08a05018) &&
2245 ic[-3].f==
instr(multi_0x08b15018) &&
2246 ic[-2].f==
instr(multi_0x08a05018) &&
2248 ic[-1].arg[0]==
ic[-1].arg[2] &&
ic[-1].arg[1] == 0x20 &&
2249 ic[ 0].f ==
instr(b_samepage__ge) &&
2250 ic[ 0].arg[0] == (size_t)&
ic[-5]) {
2264 struct arm_instr_call *
ic,
int low_addr)
2270 if (
ic[-3].
f==
instr(load_w0_word_u1_p0_imm) &&
2272 ic[-2].arg[0]==
ic[-2].arg[2] &&
ic[-2].arg[1] == 0x20 &&
2273 ic[-1].f ==
instr(b_samepage__ne) &&
2274 ic[-1].arg[0] == (size_t)&
ic[-3]) {
2287 struct arm_instr_call *
ic,
int low_addr)
2293 if (
ic[-4].
f ==
instr(mcr_mrc) &&
ic[-4].arg[0] == 0xee070f3a &&
2294 ic[-3].f ==
instr(mcr_mrc) &&
ic[-3].arg[0] == 0xee070f36 &&
2296 ic[-2].arg[0]==
ic[-2].arg[2] &&
ic[-2].arg[1] == 0x20 &&
2298 ic[-1].arg[0]==
ic[-1].arg[2] &&
ic[-1].arg[1] == 0x20) {
2309 struct arm_instr_call *
ic,
int low_addr)
2317 if (
ic[-2].
f ==
instr(load_w0_byte_u1_p1_imm) &&
2319 ic[-2].arg[1] == 0 &&
2321 ic[-1].f ==
instr(load_w0_byte_u1_p1_reg) &&
2334 struct arm_instr_call *
ic,
int low_addr)
2342 if (
ic[-2].
f ==
instr(load_w1_byte_u1_p1_imm) &&
2343 ic[-2].arg[1] == 1 &&
2347 ic[-1].arg[1] == 0) {
2357 struct arm_instr_call *
ic,
int low_addr)
2366 a =
ic[-2].arg[0]; b =
ic[-1].arg[0];
2368 if (
ic[-2].
f ==
instr(eor_regshort) &&
2369 ic[-1].f ==
instr(eor_regshort) &&
2370 ic[-2].arg[0] == a &&
ic[-2].arg[1] == b &&
ic[-2].arg[2] == b &&
2371 ic[-1].arg[0] == b &&
ic[-1].arg[1] == a &&
ic[-1].arg[2] == a &&
2372 ic[ 0].arg[0] == a &&
ic[ 0].arg[1] == b &&
ic[ 0].arg[2] == b) {
2382 struct arm_instr_call *
ic,
int low_addr)
2384 #ifdef HOST_LITTLE_ENDIAN
2391 for (i=-5; i<0; i++) {
2392 if (
ic[i].
f !=
instr(load_w1_word_u1_p0_imm) ||
2398 if (
ic[-5].arg[2] == (
size_t)(&
cpu->
cd.
arm.
r[10]) &&
2413 struct arm_instr_call *
ic,
int low_addr)
2415 #ifdef HOST_LITTLE_ENDIAN
2422 for (i=-5; i<0; i++) {
2423 if (
ic[i].
f !=
instr(store_w1_word_u1_p0_imm) ||
2429 if (
ic[-5].arg[2] == (
size_t)(&
cpu->
cd.
arm.
r[8]) &&
2444 struct arm_instr_call *
ic,
int low_addr)
2452 if (
ic[-1].arg[1] == 0)
2454 else if (
ic[-1].arg[1] & 0x80000000)
2455 ic[-1].f =
instr(cmps_neg_beq);
2457 ic[-1].f =
instr(cmps_pos_beq);
2461 if (
ic[0].
f ==
instr(b_samepage__eq)) {
2463 if (
ic[-1].arg[1] == 0)
2464 ic[-1].f =
instr(cmps0_beq_samepage);
2466 ic[-1].f =
instr(cmps_beq_samepage);
2469 !(
ic[-1].arg[1] & 0x80000000)) {
2470 ic[-1].f =
instr(tsts_lo_beq_samepage);
2473 ic[-4].
f ==
instr(load_w0_word_u1_p1_imm) &&
2474 ic[-4].arg[0] !=
ic[-4].arg[2] &&
2475 ic[-4].arg[1] == 0 &&
2476 ic[-4].arg[2] ==
ic[-3].arg[0] &&
2478 ic[-3].
f ==
instr(teqs_bne_samepage) &&
2479 ic[-3].arg[1] == 0 &&
2480 ic[-2].
f ==
instr(b_samepage__ne) &&
2482 ic[-1].arg[0] !=
ic[-4].arg[0] &&
2483 ic[-1].arg[1] == 0) {
2484 ic[-4].f =
instr(netbsd_idle);
2487 ic[-1].f =
instr(teqs_beq_samepage);
2491 if (
ic[0].
f ==
instr(b_samepage__ne)) {
2493 if (
ic[-1].arg[1] == 0)
2494 ic[-1].f =
instr(cmps0_bne_samepage);
2496 ic[-1].f =
instr(cmps_bne_samepage);
2499 !(
ic[-1].arg[1] & 0x80000000)) {
2500 ic[-1].f =
instr(tsts_lo_bne_samepage);
2503 ic[-1].f =
instr(teqs_bne_samepage);
2507 if (
ic[0].
f ==
instr(b_samepage__cc)) {
2509 ic[-1].f =
instr(cmps_bcc_samepage);
2511 if (
ic[-1].
f ==
instr(cmps_regshort)) {
2512 ic[-1].f =
instr(cmps_reg_bcc_samepage);
2516 if (
ic[0].
f ==
instr(b_samepage__hi)) {
2518 ic[-1].f =
instr(cmps_bhi_samepage);
2520 if (
ic[-1].
f ==
instr(cmps_regshort)) {
2521 ic[-1].f =
instr(cmps_reg_bhi_samepage);
2525 if (
ic[0].
f ==
instr(b_samepage__gt)) {
2527 ic[-1].f =
instr(cmps_bgt_samepage);
2531 if (
ic[0].
f ==
instr(b_samepage__le)) {
2533 ic[-1].f =
instr(cmps_ble_samepage);
2543 static void arm_switch_clear(
struct arm_instr_call *
ic,
int rd,
2566 static void arm_switch_mov1(
struct arm_instr_call *
ic,
int rd,
2589 static void arm_switch_add1(
struct arm_instr_call *
ic,
int rd,
2625 uint32_t
addr, low_pc, iword, imm = 0;
2626 unsigned char *
page;
2627 unsigned char ib[4];
2628 int condition_code, main_opcode, secondary_opcode, s_bit, rn, rd, r8;
2629 int p_bit, u_bit, w_bit, l_bit, regform, rm, any_pc_reg;
2630 void (*samepage_function)(
struct cpu *,
struct arm_instr_call *);
2633 low_pc = ((size_t)
ic - (
size_t)
cpu->
cd.
arm.cur_ic_page)
2634 /
sizeof(
struct arm_instr_call);
2646 memcpy(ib,
page + (
addr & 0xfff),
sizeof(ib));
2651 fatal(
"to_be_translated(): "
2652 "read failed: TODO\n");
2658 iword = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24);
2660 iword = ib[3] + (ib[2]<<8) + (ib[1]<<16) + (ib[0]<<24);
2663 #define DYNTRANS_TO_BE_TRANSLATED_HEAD
2665 #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
2670 condition_code = iword >> 28;
2671 main_opcode = (iword >> 24) & 15;
2672 secondary_opcode = (iword >> 21) & 15;
2673 u_bit = iword & 0x00800000;
2674 w_bit = iword & 0x00200000;
2675 s_bit = l_bit = iword & 0x00100000;
2676 rn = (iword >> 16) & 15;
2677 rd = (iword >> 12) & 15;
2678 r8 = (iword >> 8) & 15;
2687 if ((iword >> 28) == 0xf) {
2689 if ((iword & 0xfc70f000) == 0xf450f000) {
2695 switch (main_opcode) {
2701 ic->arg[1] =
addr & 0xffc;
2704 ic->arg[0] = (iword & 0x00ffffff) << 2;
2706 if (
ic->arg[0] & 0x02000000)
2707 ic->arg[0] |= 0xfc000000;
2708 if (main_opcode == 0xb)
2710 ic->arg[0] = (int32_t)(
ic->arg[0] + 8 + 1);
2718 switch (main_opcode) {
2725 if ((iword & 0x0fc000f0) == 0x00000090) {
2730 if (iword & 0x00200000) {
2748 if ((iword & 0x0f8000f0) == 0x00800090) {
2752 fatal(
"TODO: sbit mull\n");
2759 if ((iword & 0x0f900ff0) == 0x01000050) {
2761 fatal(
"TODO: q{,d}{add,sub}\n");
2764 if ((iword & 0x0ff000d0) == 0x01200010) {
2776 ic->arg[2] = (
addr & 0xffc) + 4;
2779 if ((iword & 0x0fb00ff0) == 0x1000090) {
2780 if (iword & 0x00400000)
2789 if ((iword & 0x0fff0ff0) == 0x016f0f10) {
2795 if ((iword & 0x0ff00090) == 0x01000080) {
2799 if ((iword & 0x0ff00090) == 0x01400080) {
2803 if ((iword & 0x0ff000b0) == 0x01200080) {
2807 if ((iword & 0x0ff0f090) == 0x01600080) {
2809 switch (iword & 0x60) {
2820 if ((iword & 0x0ff0f0b0) == 0x012000a0) {
2824 if ((iword & 0x0fb0fff0) == 0x0120f000 ||
2825 (iword & 0x0fb0f000) == 0x0320f000) {
2828 if (iword & 0x02000000) {
2829 if (iword & 0x00400000)
2839 if (iword & 0x00400000)
2846 imm = (imm >> 2) | ((imm & 3) << 30);
2851 if (iword & (1<<16)) arg1 |= 0x000000ff;
2852 if (iword & (1<<17)) arg1 |= 0x0000ff00;
2853 if (iword & (1<<18)) arg1 |= 0x00ff0000;
2854 if (iword & (1<<19)) arg1 |= 0xff000000;
2857 fatal(
"msr no fields\n");
2864 if ((iword & 0x0fbf0fff) == 0x010f0000) {
2871 if (iword & 0x00400000)
2878 if ((iword & 0x0e000090) == 0x00000090) {
2879 regform = !(iword & 0x00400000);
2880 imm = ((iword >> 4) & 0xf0) | (iword & 0xf);
2881 p_bit = main_opcode & 1;
2886 condition_code + (l_bit? 16 : 0)
2887 + (iword & 0x40? 32 : 0)
2889 + (iword & 0x20? 128 : 0)
2890 + (u_bit? 256 : 0) + (p_bit? 512 : 0)
2891 + (regform? 1024 : 0)];
2893 ic->arg[0] = (size_t)
2895 if (!l_bit && rd ==
ARM_PC)
2896 ic->arg[2] = (size_t)
2900 condition_code + (l_bit? 16 : 0)
2901 + (iword & 0x40? 32 : 0)
2903 + (iword & 0x20? 128 : 0)
2904 + (u_bit? 256 : 0) + (p_bit? 512 : 0)
2905 + (regform? 1024 : 0)];
2907 ic->arg[1] = (size_t)(
void *)
arm_r[iword & 0xf];
2913 if (iword & 0x80 && !(main_opcode & 2) && iword & 0x10) {
2915 fatal(
"reg form blah blah\n");
2920 if ((iword & 0x0ff000f0) == 0x01200070) {
2922 ic->arg[0] =
addr & 0xfff;
2927 if ((iword & 0x0fffffff) == 0x01a0f00e) {
2936 if ((iword & 0x0fff0ff0) == 0x01a00000 && rd !=
ARM_PC) {
2942 ic->arg[0] = (
addr & 0xfff) + 8;
2949 if ((iword & 0x0fff0fff) == 0x03a00000 && rd !=
ARM_PC) {
2950 arm_switch_clear(
ic, rd, condition_code);
2955 if ((iword & 0x0fff0fff) == 0x03a00001 && rd !=
ARM_PC) {
2956 arm_switch_mov1(
ic, rd, condition_code);
2961 if ((iword & 0x0ff00fff) == 0x02800001 && rd !=
ARM_PC
2963 arm_switch_add1(
ic, rd, condition_code);
2970 if ((main_opcode & 2) == 0)
2983 if ((secondary_opcode >= 2 && secondary_opcode <= 7)
2984 || secondary_opcode==0xa || secondary_opcode==0xb)
2986 ic->arg[1] = (size_t)(
void *)
arm_r[(iword & 0xfff) + q];
2993 imm = (imm >> 2) | ((imm & 3) << 30);
2995 if (steps != 0 && (imm != 0 && imm < 256)) {
2997 fatal(
"TODO: see cpu_arm_instr_dpi; non-zero steps but still under 256 is not implemented yet\n");
3005 if (secondary_opcode == 0xf && !regform) {
3006 secondary_opcode = 0xd;
3007 ic->arg[1] = ~
ic->arg[1];
3016 if (!any_pc_reg && regform && (iword & 0xfff) <
ARM_PC) {
3019 16 * secondary_opcode + (s_bit? 256 : 0)];
3022 16 * secondary_opcode + (s_bit? 256 : 0) +
3023 (any_pc_reg? 512 : 0) + (regform? 1024 : 0)];
3025 if (
ic->f ==
instr(eor_regshort))
3027 if (iword == 0xe113000c)
3039 & 0x3f0) + condition_code];
3042 if (!l_bit && rd ==
ARM_PC)
3046 0x3f0) + condition_code];
3048 imm = iword & 0xfff;
3049 if (main_opcode < 6)
3052 ic->arg[1] = (size_t)(
void *)
arm_r[iword & 0xfff];
3053 if ((iword & 0x0e000010) == 0x06000010) {
3056 ic->arg[0] =
addr & 0xfff;
3059 if (rn ==
ARM_PC && rd !=
ARM_PC && main_opcode < 6 && l_bit) {
3060 unsigned char *p =
page;
3061 int ofs = (
addr & 0xfff) + 8, max = 0xffc;
3062 int b_bit = iword & 0x00400000;
3066 ofs += (iword & 0xfff);
3068 ofs -= (iword & 0xfff);
3071 if (ofs >= 0 && ofs <= max && p != NULL) {
3072 unsigned char cbuf[4];
3073 int len = b_bit? 1 : 4;
3074 uint32_t x, a = (
addr & 0xfffff000) | ofs;
3079 memcpy(cbuf, p + (a & 0xfff), len);
3085 x = cbuf[0] + (cbuf[1]<<8) +
3086 (cbuf[2]<<16) + (cbuf[3]<<24);
3088 x = cbuf[3] + (cbuf[2]<<8) +
3089 (cbuf[1]<<16) + (cbuf[0]<<24);
3095 if (iword == 0xe4b09004)
3097 if (iword == 0xe4a17004)
3104 ic->arg[1] = (size_t)iword;
3110 #if defined(HOST_LITTLE_ENDIAN) && !defined(GATHER_BDT_STATISTICS)
3122 int i = 0, j = iword;
3123 j = ((j & 0x00800000) >> 16) | ((j & 0x00100000) >> 14)
3124 | ((j & 0x00040000) >> 13) | ((j & 0x00010000) >> 12)
3125 | ((j & 0x00000100) >> 5) | ((j & 0x00000040) >> 4)
3126 | ((j & 0x00000010) >> 3) | ((j & 0x00000004) >> 2);
3128 if ((iword & 0x0fffffff) ==
3131 [i*16 + condition_code];
3140 fatal(
"TODO: bdt with PC as base\n");
3147 if (main_opcode == 0x0a) {
3152 if (condition_code == 0xe &&
3156 if (iword == 0xcaffffed)
3159 if (iword == 0xaafffff9)
3175 ic->arg[1] =
addr & 0xffc;
3176 ic->arg[2] = (
addr & 0xffc) + 4;
3178 ic->arg[0] = (iword & 0x00ffffff) << 2;
3180 if (
ic->arg[0] & 0x02000000)
3181 ic->arg[0] |= 0xfc000000;
3185 ic->arg[0] = (int32_t)(
ic->arg[0] + 8);
3194 uint32_t mask_within_page =
3198 uint32_t old_pc =
addr;
3199 uint32_t new_pc = old_pc + (int32_t)
ic->arg[0];
3200 if ((old_pc & ~mask_within_page) ==
3201 (new_pc & ~mask_within_page)) {
3202 ic->f = samepage_function;
3203 ic->arg[0] = (size_t) (
3205 ((new_pc & mask_within_page) >>
3207 ic->arg[1] = (size_t) (
3209 (((
addr & mask_within_page) + 4) >>
3211 }
else if (main_opcode == 0x0a) {
3213 ic->arg[0] +=
ic->arg[1];
3217 if (main_opcode == 0xa && (condition_code <= 1
3218 || condition_code == 3 || condition_code == 8
3219 || condition_code == 12 || condition_code == 13))
3222 if (iword == 0x1afffffc)
3226 if (iword == 0x8afffffa)
3237 if ((iword & 0x0fe00fff) == 0x0c400000) {
3240 fatal(
"TODO: mar/mra DSP instructions!\n");
3245 if ((iword & 0x0fe00000) == 0x0c400000) {
3247 fatal(
"MCRR/MRRC: TODO\n");
3259 ic->arg[0] =
addr & 0xfff;
3262 fatal(
"LDC/STC: TODO\n");
3268 if ((iword & 0x0ff00ff0) == 0x0e200010) {
3272 fatal(
"TODO: mia* DSP instructions!\n");
3284 if (iword == 0xee070f9a)
3293 ic->arg[0] =
addr & 0xfff;
3294 if (iword == 0xef8c64eb) {
3297 }
else if (iword == 0xef8c64be) {
3308 #define DYNTRANS_TO_BE_TRANSLATED_TAIL
3310 #undef DYNTRANS_TO_BE_TRANSLATED_TAIL