filename | src/aica/armdasm.c |
changeset | 43:0cf3e339cc59 |
prev | 30:89b30313d757 |
next | 48:de09cb63b4d0 |
author | nkeynes |
date | Mon Dec 26 11:52:56 2005 +0000 (17 years ago) |
permissions | -rw-r--r-- |
last change | Default ARM to not-running for sanity's sake Stop machine on UNIMP abort |
view | annotate | diff | log | raw |
1 /**
2 * $Id: armdasm.c,v 1.7 2005-12-26 11:47:15 nkeynes Exp $
3 *
4 * armdasm.c 21 Aug 2004 - ARM7tdmi (ARMv4) disassembler
5 *
6 * Copyright (c) 2005 Nathan Keynes.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
19 #include "aica/armcore.h"
20 #include "aica/armdasm.h"
21 #include <stdlib.h>
23 #define COND(ir) (ir>>28)
24 #define OPCODE(ir) ((ir>>20)&0x1F)
25 #define GRP(ir) ((ir>>26)&0x03)
26 #define IFLAG(ir) (ir&0x02000000)
27 #define SFLAG(ir) (ir&0x00100000)
28 #define PFLAG(ir) (ir&0x01000000)
29 #define UFLAG(ir) (ir&0x00800000)
30 #define BFLAG(ir) (ir&0x00400000)
31 #define WFLAG(ir) (ir&0x00200000)
32 #define LFLAG(ir) SFLAG(ir)
33 #define RN(ir) ((ir>>16)&0x0F)
34 #define RD(ir) ((ir>>12)&0x0F)
35 #define RS(ir) ((ir>>8)&0x0F)
36 #define RM(ir) (ir&0x0F)
38 #define IMM8(ir) (ir&0xFF)
39 #define IMM12(ir) (ir&0xFFF)
40 #define SHIFTIMM(ir) ((ir>>7)&0x1F)
41 #define IMMROT(ir) ((ir>>7)&0x1E)
42 #define SHIFT(ir) ((ir>>4)&0x07)
43 #define DISP24(ir) ((ir&0x00FFFFFF))
44 #define FSXC(ir) msrFieldMask[RN(ir)]
45 #define ROTIMM12(ir) ROTATE_RIGHT_LONG(IMM8(ir),IMMROT(ir))
46 #define SIGNEXT24(n) ((n&0x00800000) ? (n|0xFF000000) : (n&0x00FFFFFF))
50 const struct reg_desc_struct arm_reg_map[] =
51 { {"R0", REG_INT, &armr.r[0]}, {"R1", REG_INT, &armr.r[1]},
52 {"R2", REG_INT, &armr.r[2]}, {"R3", REG_INT, &armr.r[3]},
53 {"R4", REG_INT, &armr.r[4]}, {"R5", REG_INT, &armr.r[5]},
54 {"R6", REG_INT, &armr.r[6]}, {"R7", REG_INT, &armr.r[7]},
55 {"R8", REG_INT, &armr.r[8]}, {"R9", REG_INT, &armr.r[9]},
56 {"R10",REG_INT, &armr.r[10]}, {"R11",REG_INT, &armr.r[11]},
57 {"R12",REG_INT, &armr.r[12]}, {"R13",REG_INT, &armr.r[13]},
58 {"R14",REG_INT, &armr.r[14]}, {"R15",REG_INT, &armr.r[15]},
59 {"CPSR", REG_INT, &armr.cpsr}, {"SPSR", REG_INT, &armr.spsr},
60 {NULL, 0, NULL} };
63 const struct cpu_desc_struct arm_cpu_desc =
64 { "ARM7", arm_disasm_instruction, arm_execute_instruction, arm_has_page,
65 arm_set_breakpoint, arm_clear_breakpoint, arm_get_breakpoint, 4,
66 (char *)&armr, sizeof(armr), arm_reg_map,
67 &armr.r[15], &armr.icount };
68 const struct cpu_desc_struct armt_cpu_desc =
69 { "ARM7T", armt_disasm_instruction, arm_execute_instruction, arm_has_page, 2,
70 (char*)&armr, sizeof(armr), arm_reg_map,
71 &armr.r[15], &armr.icount };
76 char *conditionNames[] = { "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC",
77 "HI", "LS", "GE", "LT", "GT", "LE", " " /*AL*/, "NV" };
79 /* fsxc */
80 char *msrFieldMask[] = { "", "c", "x", "xc", "s", "sc", "sx", "sxc",
81 "f", "fc", "fx", "fxc", "fs", "fsc", "fsx", "fsxc" };
82 char *ldmModes[] = { "DA", "IA", "DB", "IB" };
84 #define UNIMP(ir) snprintf( buf, len, "??? " )
86 int arm_disasm_shift_operand( uint32_t ir, char *buf, int len )
87 {
88 uint32_t operand, tmp;
89 if( IFLAG(ir) == 0 ) {
90 switch(SHIFT(ir)) {
91 case 0: /* (Rm << imm) */
92 tmp = SHIFTIMM(ir);
93 if( tmp != 0 ) {
94 return snprintf(buf, len, "R%d << %d", RM(ir), tmp );
95 } else {
96 return snprintf(buf, len, "R%d", RM(ir));
97 }
98 case 1: /* (Rm << Rs) */
99 return snprintf(buf, len, "R%d << R%d", RM(ir), RS(ir) );
100 case 2: /* (Rm >> imm) */
101 return snprintf(buf, len, "R%d >> %d", RM(ir), SHIFTIMM(ir) );
102 case 3: /* (Rm >> Rs) */
103 return snprintf(buf, len, "R%d >> R%d", RM(ir), RS(ir) );
104 case 4: /* (Rm >>> imm) */
105 return snprintf(buf, len, "R%d >>> %d", RM(ir), SHIFTIMM(ir) );
106 case 5: /* (Rm >>> Rs) */
107 return snprintf(buf, len, "R%d >>> R%d", RM(ir), RS(ir) );
108 case 6:
109 tmp = SHIFTIMM(ir);
110 if( tmp == 0 ) /* RRX aka rotate with carry */
111 return snprintf(buf, len, "R%d roc 1", RM(ir) );
112 else
113 return snprintf(buf, len, "R%d rot %d", RM(ir), SHIFTIMM(ir) );
114 case 7:
115 return snprintf(buf, len, "R%d rot R%d", RM(ir), RS(ir) );
116 }
117 } else {
118 operand = IMM8(ir);
119 tmp = IMMROT(ir);
120 operand = ROTATE_RIGHT_LONG(operand, tmp);
121 return snprintf(buf, len, "%08X", operand );
122 }
123 }
125 static int arm_disasm_address_index( uint32_t ir, char *buf, int len )
126 {
127 uint32_t tmp;
129 switch(SHIFT(ir)) {
130 case 0: /* (Rm << imm) */
131 tmp = SHIFTIMM(ir);
132 if( tmp != 0 ) {
133 return snprintf( buf, len, "R%d << %d", RM(ir), tmp );
134 } else {
135 return snprintf( buf, len, "R%d", RM(ir) );
136 }
137 case 2: /* (Rm >> imm) */
138 return snprintf( buf, len, "R%d >> %d", RM(ir), SHIFTIMM(ir) );
139 case 4: /* (Rm >>> imm) */
140 return snprintf( buf, len, "R%d >>> %d", RM(ir), SHIFTIMM(ir) );
141 case 6:
142 tmp = SHIFTIMM(ir);
143 if( tmp == 0 ) /* RRX aka rotate with carry */
144 return snprintf( buf, len, "R%d roc 1", RM(ir) );
145 else
146 return snprintf( buf, len, "R%d rot %d", RM(ir), tmp );
147 default:
148 return UNIMP(ir);
149 }
150 }
152 static int arm_disasm_address_operand( uint32_t ir, char *buf, int len, int pc )
153 {
154 char shift[32];
156 char sign = UFLAG(ir) ? '+' : '-';
157 /* I P U . W */
158 switch( (ir>>21)&0x19 ) {
159 case 0: /* Rn -= imm offset (post-indexed) [5.2.8 A5-28] */
160 case 1:
161 return snprintf( buf, len, "[R%d], R%d %c= %04X", RN(ir), RN(ir), sign, IMM12(ir) );
162 case 8: /* Rn - imm offset [5.2.2 A5-20] */
163 if( RN(ir) == 15 ) { /* PC relative - decode here */
164 return snprintf( buf, len, "[$%08Xh]", pc + 8 +
165 (UFLAG(ir) ? IMM12(ir) : -IMM12(ir)) );
166 } else {
167 return snprintf( buf, len, "[R%d %c %04X]", RN(ir), sign, IMM12(ir) );
168 }
169 case 9: /* Rn -= imm offset (pre-indexed) [5.2.5 A5-24] */
170 return snprintf( buf, len, "[R%d %c= %04X]", RN(ir), sign, IMM12(ir) );
171 case 16: /* Rn -= Rm (post-indexed) [5.2.10 A5-32 ] */
172 case 17:
173 arm_disasm_address_index( ir, shift, sizeof(shift) );
174 return snprintf( buf, len, "[R%d], R%d %c= %s", RN(ir), RN(ir), sign, shift );
175 case 24: /* Rn - Rm [5.2.4 A5-23] */
176 arm_disasm_address_index( ir, shift, sizeof(shift) );
177 return snprintf( buf, len, "[R%d %c %s]", RN(ir), sign, shift );
178 case 25: /* RN -= Rm (pre-indexed) [5.2.7 A5-26] */
179 arm_disasm_address_index( ir, shift, sizeof(shift) );
180 return snprintf( buf, len, "[R%d %c= %s]", RN(ir), sign, shift );
181 default:
182 return UNIMP(ir); /* Unreachable */
183 }
184 }
186 uint32_t arm_disasm_instruction( uint32_t pc, char *buf, int len, char *opcode )
187 {
188 char operand[32];
189 uint32_t ir = arm_read_long(pc);
190 int i,j;
192 sprintf( opcode, "%02X %02X %02X %02X", ir&0xFF, (ir>>8) & 0xFF,
193 (ir>>16)&0xFF, (ir>>24) );
195 if( COND(ir) == 0x0F ) {
196 UNIMP(ir);
197 return pc+4;
198 }
199 char *cond = conditionNames[COND(ir)];
201 switch( GRP(ir) ) {
202 case 0:
203 if( (ir & 0x0D900000) == 0x01000000 ) {
204 /* Instructions that aren't actual data processing */
205 switch( ir & 0x0FF000F0 ) {
206 case 0x01200010: /* BXcc */
207 snprintf(buf, len, "BX%s R%d", cond, RM(ir));
208 break;
209 case 0x01000000: /* MRS Rd, CPSR */
210 snprintf(buf, len, "MRS%s R%d, CPSR", cond, RD(ir));
211 break;
212 case 0x01400000: /* MRS Rd, SPSR */
213 snprintf(buf, len, "MRS%s R%d, SPSR", cond, RD(ir));
214 break;
215 case 0x01200000: /* MSR CPSR, Rm */
216 snprintf(buf, len, "MSR%s CPSR_%s, R%d", cond, FSXC(ir), RM(ir));
217 break;
218 case 0x01600000: /* MSR SPSR, Rm */
219 snprintf(buf, len, "MSR%s SPSR_%s, R%d", cond, FSXC(ir), RM(ir));
220 break;
221 case 0x03200000: /* MSR CPSR, imm */
222 snprintf(buf, len, "MSR%s CPSR_%s, #%08X", cond, FSXC(ir), ROTIMM12(ir));
223 break;
224 case 0x03600000: /* MSR SPSR, imm */
225 snprintf(buf, len, "MSR%s SPSR_%s, #%08X", cond, FSXC(ir), ROTIMM12(ir));
226 break;
227 default:
228 UNIMP();
229 }
230 } else if( (ir & 0x0E000090) == 0x00000090 ) {
231 /* Neither are these */
232 switch( (ir>>5)&0x03 ) {
233 case 0:
234 /* Arithmetic extension area */
235 switch(OPCODE(ir)) {
236 case 0: /* MUL */
237 snprintf(buf,len, "MUL%s R%d, R%d, R%d", cond, RN(ir), RM(ir), RS(ir) );
238 break;
239 case 1: /* MULS */
240 break;
241 case 2: /* MLA */
242 snprintf(buf,len, "MLA%s R%d, R%d, R%d, R%d", cond, RN(ir), RM(ir), RS(ir), RD(ir) );
243 break;
244 case 3: /* MLAS */
245 break;
246 case 8: /* UMULL */
247 snprintf(buf,len, "UMULL%s R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
248 break;
249 case 9: /* UMULLS */
250 break;
251 case 10: /* UMLAL */
252 snprintf(buf,len, "UMLAL%s R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
253 break;
254 case 11: /* UMLALS */
255 break;
256 case 12: /* SMULL */
257 snprintf(buf,len, "SMULL%s R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
258 break;
259 case 13: /* SMULLS */
260 break;
261 case 14: /* SMLAL */
262 snprintf(buf,len, "SMLAL%s R%d, R%d, R%d, R%d", cond, RD(ir), RN(ir), RM(ir), RS(ir) );
263 break;
264 case 15: /* SMLALS */
266 break;
267 case 16: /* SWP */
268 snprintf(buf,len, "SWP%s R%d, R%d, [R%d]", cond, RD(ir), RN(ir), RM(ir) );
269 break;
270 case 20: /* SWPB */
271 snprintf(buf,len, "SWPB%s R%d, R%d, [R%d]", cond, RD(ir), RN(ir), RM(ir) );
272 break;
273 default:
274 UNIMP(ir);
275 }
276 break;
277 case 1:
278 if( LFLAG(ir) ) {
279 /* LDRH */
280 } else {
281 /* STRH */
282 }
283 break;
284 case 2:
285 if( LFLAG(ir) ) {
286 /* LDRSB */
287 } else {
288 UNIMP(ir);
289 }
290 break;
291 case 3:
292 if( LFLAG(ir) ) {
293 /* LDRSH */
294 } else {
295 UNIMP(ir);
296 }
297 break;
298 }
299 } else {
300 /* Data processing */
302 switch(OPCODE(ir)) {
303 case 0: /* AND Rd, Rn, operand */
304 arm_disasm_shift_operand(ir, operand, sizeof(operand));
305 snprintf(buf, len, "AND%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
306 break;
307 case 1: /* ANDS Rd, Rn, operand */
308 arm_disasm_shift_operand(ir, operand, sizeof(operand));
309 snprintf(buf, len, "ANDS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
310 break;
311 case 2: /* EOR Rd, Rn, operand */
312 arm_disasm_shift_operand(ir, operand, sizeof(operand));
313 snprintf(buf, len, "EOR%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
314 break;
315 case 3: /* EORS Rd, Rn, operand */
316 arm_disasm_shift_operand(ir, operand, sizeof(operand));
317 snprintf(buf, len, "EORS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
318 break;
319 case 4: /* SUB Rd, Rn, operand */
320 arm_disasm_shift_operand(ir, operand, sizeof(operand));
321 snprintf(buf, len, "SUB%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
322 break;
323 case 5: /* SUBS Rd, Rn, operand */
324 arm_disasm_shift_operand(ir, operand, sizeof(operand));
325 snprintf(buf, len, "SUBS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
326 break;
327 case 6: /* RSB Rd, Rn, operand */
328 arm_disasm_shift_operand(ir, operand, sizeof(operand));
329 snprintf(buf, len, "RSB%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
330 break;
331 case 7: /* RSBS Rd, Rn, operand */
332 arm_disasm_shift_operand(ir, operand, sizeof(operand));
333 snprintf(buf, len, "RSBS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
334 break;
335 case 8: /* ADD Rd, Rn, operand */
336 arm_disasm_shift_operand(ir, operand, sizeof(operand));
337 snprintf(buf, len, "ADD%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
338 break;
339 case 9: /* ADDS Rd, Rn, operand */
340 arm_disasm_shift_operand(ir, operand, sizeof(operand));
341 snprintf(buf, len, "ADDS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
342 break;
343 case 10: /* ADC Rd, Rn, operand */
344 arm_disasm_shift_operand(ir, operand, sizeof(operand));
345 snprintf(buf, len, "ADC%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
346 break;
347 case 11: /* ADCS Rd, Rn, operand */
348 arm_disasm_shift_operand(ir, operand, sizeof(operand));
349 snprintf(buf, len, "ADCS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
350 break;
351 case 12: /* SBC Rd, Rn, operand */
352 arm_disasm_shift_operand(ir, operand, sizeof(operand));
353 snprintf(buf, len, "SBC%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
354 break;
355 case 13: /* SBCS Rd, Rn, operand */
356 arm_disasm_shift_operand(ir, operand, sizeof(operand));
357 snprintf(buf, len, "SBCS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
358 break;
359 case 14: /* RSC Rd, Rn, operand */
360 arm_disasm_shift_operand(ir, operand, sizeof(operand));
361 snprintf(buf, len, "RSC%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
362 break;
363 case 15: /* RSCS Rd, Rn, operand */
364 arm_disasm_shift_operand(ir, operand, sizeof(operand));
365 snprintf(buf, len, "RSCS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
366 break;
367 case 16: /* TST Rd, Rn, operand */
368 arm_disasm_shift_operand(ir, operand, sizeof(operand));
369 snprintf(buf, len, "TST%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
370 break;
371 case 18: /* TEQ Rd, Rn, operand */
372 arm_disasm_shift_operand(ir, operand, sizeof(operand));
373 snprintf(buf, len, "TEQ%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
374 break;
375 case 20: /* CMP Rd, Rn, operand */
376 arm_disasm_shift_operand(ir, operand, sizeof(operand));
377 snprintf(buf, len, "CMP%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
378 break;
379 case 22: /* CMN Rd, Rn, operand */
380 arm_disasm_shift_operand(ir, operand, sizeof(operand));
381 snprintf(buf, len, "CMN%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
382 break;
383 case 24: /* ORR Rd, Rn, operand */
384 arm_disasm_shift_operand(ir, operand, sizeof(operand));
385 snprintf(buf, len, "ORR%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
386 break;
387 case 25: /* ORRS Rd, Rn, operand */
388 arm_disasm_shift_operand(ir, operand, sizeof(operand));
389 snprintf(buf, len, "ORRS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
390 break;
391 case 26: /* MOV Rd, Rn, operand */
392 arm_disasm_shift_operand(ir, operand, sizeof(operand));
393 snprintf(buf, len, "MOV%s R%d, %s", cond, RD(ir), operand);
394 break;
395 case 27: /* MOVS Rd, Rn, operand */
396 arm_disasm_shift_operand(ir, operand, sizeof(operand));
397 snprintf(buf, len, "MOVS%s R%d, %s", cond, RD(ir), operand);
398 break;
399 case 28: /* BIC Rd, Rn, operand */
400 arm_disasm_shift_operand(ir, operand, sizeof(operand));
401 snprintf(buf, len, "BIC%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
402 break;
403 case 29: /* BICS Rd, Rn, operand */
404 arm_disasm_shift_operand(ir, operand, sizeof(operand));
405 snprintf(buf, len, "BICS%s R%d, R%d, %s", cond, RD(ir), RN(ir), operand);
406 break;
407 case 30: /* MVN Rd, Rn, operand */
408 arm_disasm_shift_operand(ir, operand, sizeof(operand));
409 snprintf(buf, len, "MVN%s R%d, %s", cond, RD(ir), operand);
410 break;
411 case 31: /* MVNS Rd, Rn, operand */
412 arm_disasm_shift_operand(ir, operand, sizeof(operand));
413 snprintf(buf, len, "MVNS%s R%d, %s", cond, RD(ir), operand);
414 break;
415 default:
416 UNIMP(ir);
417 }
418 }
419 break;
420 case 1: /* Load/store */
421 arm_disasm_address_operand( ir, operand, sizeof(operand), pc );
422 switch( (ir>>20)&0x17 ) {
423 case 0:
424 case 16:
425 case 18:
426 snprintf(buf, len, "STR%s R%d, %s", cond, RD(ir), operand );
427 break;
428 case 1:
429 case 17:
430 case 19:
431 snprintf(buf, len, "LDR%s R%d, %s", cond, RD(ir), operand );
432 break;
433 case 2:
434 snprintf(buf, len, "STRT%s R%d, %s", cond, RD(ir), operand );
435 break;
436 case 3:
437 snprintf(buf, len, "LDRT%s R%d, %s", cond, RD(ir), operand );
438 break;
439 case 4:
440 case 20:
441 case 22:
442 snprintf(buf, len, "STRB%s R%d, %s", cond, RD(ir), operand );
443 break;
444 case 5:
445 case 21:
446 case 23:
447 snprintf(buf, len, "LDRB%s R%d, %s", cond, RD(ir), operand );
448 break;
449 case 6:
450 snprintf(buf, len, "STRBT%s R%d, %s", cond, RD(ir), operand );
451 break;
452 case 7:
453 snprintf(buf, len, "LDRBT%s R%d, %s", cond, RD(ir), operand );
454 break;
455 }
456 break;
457 case 2:
458 if( (ir & 0x02000000) == 0x02000000 ) {
459 int32_t offset = SIGNEXT24(ir&0x00FFFFFF) << 2;
460 if( (ir & 0x01000000) == 0x01000000 ) {
461 snprintf( buf, len, "BL%s $%08Xh", cond, pc + offset + 8 );
462 } else {
463 snprintf( buf, len, "B%s $%08Xh", cond, pc + offset + 8 );
464 }
465 } else {
466 /* Load/store multiple */
467 j = snprintf( buf, len, LFLAG(ir) ? "LDM%s%s R%d%c,":"STM%s%s R%d%c,",
468 ldmModes[(ir>>23)&0x03], cond, RN(ir), WFLAG(ir)?'!':' ' );
469 buf += j;
470 len -= j;
471 for( i = 0; i<16 && len > 2; i++ ) {
472 if( (ir >> i)&1 ) {
473 j = snprintf( buf, len, "R%d", i );
474 buf+=j;
475 len-=j;
476 }
477 }
478 if( SFLAG(ir) && len > 0 ) {
479 buf[0] = '^';
480 buf[1] = '\0';
481 }
482 }
483 break;
484 case 3: /* Copro */
485 UNIMP(ir);
486 break;
487 }
491 return pc+4;
492 }
495 uint32_t armt_disasm_instruction( uint32_t pc, char *buf, int len, char *opcode )
496 {
497 uint32_t ir = arm_read_word(pc);
498 sprintf( opcode, "%02X %02X", ir&0xFF, (ir>>8) );
499 UNIMP(ir);
500 return pc+2;
501 }
.