/[gxemul]/trunk/src/cpu_arm.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/src/cpu_arm.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 6 by dpavlin, Mon Oct 8 16:18:11 2007 UTC revision 10 by dpavlin, Mon Oct 8 16:18:27 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_arm.c,v 1.2 2005/06/02 13:52:57 debug Exp $   *  $Id: cpu_arm.c,v 1.19 2005/06/27 16:44:54 debug Exp $
29   *   *
30   *  ARM CPU emulation.   *  ARM CPU emulation.
31   *   *
32   *  TODO: This is just a dummy so far.   *  Whenever there is a reference to "(1)", that means
33     *  "http://www.pinknoise.demon.co.uk/ARMinstrs/ARMinstrs.html".
34   */   */
35    
36  #include <stdio.h>  #include <stdio.h>
# Line 67  int arm_cpu_family_init(struct cpu_famil Line 68  int arm_cpu_family_init(struct cpu_famil
68  #include "symbol.h"  #include "symbol.h"
69    
70    
71    /*  instr uses the same names as in cpu_arm_instr.c  */
72    #define instr(n) arm_instr_ ## n
73    
74    static char *arm_condition_string[16] = {
75            "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
76            "hi", "ls", "ge", "lt", "gt", "le", ""/*Always*/, "(INVALID)" };
77    
78    /*  ARM symbolic register names:  */
79    static char *arm_regname[N_ARM_REGS] = {
80            "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
81            "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc" };
82    
83    /* Data processing instructions:  */
84    static char *arm_dpiname[16] = {
85            "and", "eor", "sub", "rsb", "add", "adc", "sbc", "rsc",
86            "tst", "teq", "cmp", "cmn", "orr", "mov", "bic", "mvn" };
87    static int arm_dpi_uses_d[16] = {
88            1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1 };
89    static int arm_dpi_uses_n[16] = {
90            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0 };
91    
92  extern volatile int single_step;  extern volatile int single_step;
93  extern int old_show_trace_tree;    extern int old_show_trace_tree;  
94  extern int old_instruction_trace;  extern int old_instruction_trace;
# Line 77  extern int quiet_mode; Line 99  extern int quiet_mode;
99  /*  /*
100   *  arm_cpu_new():   *  arm_cpu_new():
101   *   *
102   *  Create a new ARM cpu object.   *  Create a new ARM cpu object by filling in the CPU struct.
103     *  Return 1 on success, 0 if cpu_type_name isn't a valid ARM processor.
104   */   */
105  struct cpu *arm_cpu_new(struct memory *mem, struct machine *machine,  int arm_cpu_new(struct cpu *cpu, struct memory *mem,
106          int cpu_id, char *cpu_type_name)          struct machine *machine, int cpu_id, char *cpu_type_name)
107  {  {
108          struct cpu *cpu;          if (strcmp(cpu_type_name, "ARM") != 0)
109                    return 0;
110    
111          if (cpu_type_name == NULL || strcmp(cpu_type_name, "ARM") != 0)          cpu->memory_rw = arm_memory_rw;
                 return NULL;  
   
         cpu = malloc(sizeof(struct cpu));  
         if (cpu == NULL) {  
                 fprintf(stderr, "out of memory\n");  
                 exit(1);  
         }  
112    
113          memset(cpu, 0, sizeof(struct cpu));          cpu->cd.arm.flags = ARM_FLAG_I | ARM_FLAG_F | ARM_MODE_USR32;
         cpu->memory_rw          = arm_memory_rw;  
         cpu->name               = cpu_type_name;  
         cpu->mem                = mem;  
         cpu->machine            = machine;  
         cpu->cpu_id             = cpu_id;  
         cpu->byte_order         = EMUL_BIG_ENDIAN;  
         cpu->bootstrap_cpu_flag = 0;  
         cpu->running            = 0;  
114    
115          /*  Only show name and caches etc for CPU nr 0 (in SMP machines):  */          /*  Only show name and caches etc for CPU nr 0:  */
116          if (cpu_id == 0) {          if (cpu_id == 0) {
117                  debug("%s", cpu->name);                  debug("%s", cpu->name);
118          }          }
119    
120          return cpu;          return 1;
121  }  }
122    
123    
# Line 117  struct cpu *arm_cpu_new(struct memory *m Line 126  struct cpu *arm_cpu_new(struct memory *m
126   */   */
127  void arm_cpu_dumpinfo(struct cpu *cpu)  void arm_cpu_dumpinfo(struct cpu *cpu)
128  {  {
129          debug("\n");          debug(" (%i MB translation cache)\n",
130                (int)(ARM_TRANSLATION_CACHE_SIZE / 1048576));
         /*  TODO  */  
131  }  }
132    
133    
# Line 142  void arm_cpu_list_available_types(void) Line 150  void arm_cpu_list_available_types(void)
150  void arm_cpu_register_match(struct machine *m, char *name,  void arm_cpu_register_match(struct machine *m, char *name,
151          int writeflag, uint64_t *valuep, int *match_register)          int writeflag, uint64_t *valuep, int *match_register)
152  {  {
153          int cpunr = 0;          int i, cpunr = 0;
154    
155          /*  CPU number:  */          /*  CPU number:  */
156    
157          /*  TODO  */          /*  TODO  */
158    
159          /*  Register name:  */          /*  Register names:  */
160          if (strcasecmp(name, "pc") == 0) {          for (i=0; i<N_ARM_REGS; i++) {
161                  if (writeflag) {                  if (strcasecmp(name, arm_regname[i]) == 0) {
162                          m->cpus[cpunr]->pc = *valuep;                          if (writeflag) {
163                  } else                                  m->cpus[cpunr]->cd.arm.r[i] = *valuep;
164                          *valuep = m->cpus[cpunr]->pc;                                  if (i == ARM_PC)
165                  *match_register = 1;                                          m->cpus[cpunr]->pc = *valuep;
166                            } else
167                                    *valuep = m->cpus[cpunr]->cd.arm.r[i];
168                            *match_register = 1;
169                    }
170          }          }
171    }
172    
173    
174          /*  TODO: _LOTS_ of stuff.  */  /*
175     *  arm_cpu_register_dump():
176     *
177     *  Dump cpu registers in a relatively readable format.
178     *  
179     *  gprs: set to non-zero to dump GPRs and some special-purpose registers.
180     *  coprocs: set bit 0..3 to dump registers in coproc 0..3.
181     */
182    void arm_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
183    {
184            char *symbol;
185            uint64_t offset;
186            int i, x = cpu->cpu_id;
187    
188            if (gprs) {
189                    symbol = get_symbol_name(&cpu->machine->symbol_context,
190                        cpu->cd.arm.r[ARM_PC], &offset);
191                    debug("cpu%i:  flags = ", x);
192                    debug("%s%s%s%s%s%s",
193                        (cpu->cd.arm.flags & ARM_FLAG_N)? "N" : "n",
194                        (cpu->cd.arm.flags & ARM_FLAG_Z)? "Z" : "z",
195                        (cpu->cd.arm.flags & ARM_FLAG_C)? "C" : "c",
196                        (cpu->cd.arm.flags & ARM_FLAG_V)? "V" : "v",
197                        (cpu->cd.arm.flags & ARM_FLAG_I)? "I" : "i",
198                        (cpu->cd.arm.flags & ARM_FLAG_F)? "F" : "f");
199                    debug("   pc = 0x%08x", (int)cpu->cd.arm.r[ARM_PC]);
200    
201                    /*  TODO: Flags  */
202    
203                    debug("  <%s>\n", symbol != NULL? symbol : " no symbol ");
204    
205                    for (i=0; i<N_ARM_REGS; i++) {
206                            if ((i % 4) == 0)
207                                    debug("cpu%i:", x);
208                            if (i != ARM_PC)
209                                    debug("  %s = 0x%08x", arm_regname[i],
210                                        (int)cpu->cd.arm.r[i]);
211                            if ((i % 4) == 3)
212                                    debug("\n");
213                    }
214            }
215  }  }
216    
217    
# Line 173  void arm_cpu_register_match(struct machi Line 227  void arm_cpu_register_match(struct machi
227   *  register contents) will not be shown, and addr will be used instead of   *  register contents) will not be shown, and addr will be used instead of
228   *  cpu->pc for relative addresses.   *  cpu->pc for relative addresses.
229   */                       */                    
230  int arm_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr,  int arm_cpu_disassemble_instr(struct cpu *cpu, unsigned char *ib,
231          int running, uint64_t dumpaddr, int bintrans)          int running, uint64_t dumpaddr, int bintrans)
232  {  {
233          uint32_t iw;          uint32_t iw, tmp;
234            int main_opcode, secondary_opcode, s_bit, r16, r12, r8;
235            int p_bit, u_bit, b_bit, w_bit, l_bit;
236            char *symbol, *condition;
237            uint64_t offset;
238    
239          if (running)          if (running)
240                  dumpaddr = cpu->pc;                  dumpaddr = cpu->pc;
241    
242            symbol = get_symbol_name(&cpu->machine->symbol_context,
243                dumpaddr, &offset);
244            if (symbol != NULL && offset == 0)
245                    debug("<%s>\n", symbol);
246    
247            if (cpu->machine->ncpus > 1 && running)
248                    debug("cpu%i:\t", cpu->cpu_id);
249    
250          debug("%08x:  ", (int)dumpaddr);          debug("%08x:  ", (int)dumpaddr);
251    
252          iw = instr[0] + (instr[1] << 8) + (instr[2] << 16) + (instr[3] << 24);          if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
253                    iw = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24);
254            else
255                    iw = ib[3] + (ib[2]<<8) + (ib[1]<<16) + (ib[0]<<24);
256          debug("%08x\t", (int)iw);          debug("%08x\t", (int)iw);
257    
258          debug("arm_cpu_disassemble_instr(): TODO\n");          condition = arm_condition_string[iw >> 28];
259            main_opcode = (iw >> 24) & 15;
260            secondary_opcode = (iw >> 21) & 15;
261            u_bit = (iw >> 23) & 1;
262            b_bit = (iw >> 22) & 1;
263            w_bit = (iw >> 21) & 1;
264            s_bit = l_bit = (iw >> 20) & 1;
265            r16 = (iw >> 16) & 15;
266            r12 = (iw >> 12) & 15;
267            r8 = (iw >> 8) & 15;
268    
269            switch (main_opcode) {
270            case 0x0:
271            case 0x1:
272            case 0x2:
273            case 0x3:
274                    /*
275                     *  See (1):
276                     *  xxxx000a aaaSnnnn ddddcccc ctttmmmm  Register form
277                     *  xxxx001a aaaSnnnn ddddrrrr bbbbbbbb  Immediate form
278                     */
279                    if (iw & 0x80 && !(main_opcode & 2)) {
280                            debug("UNIMPLEMENTED reg (c!=0)\n");
281                            break;
282                    }
283    
284                    debug("%s%s%s\t", arm_dpiname[secondary_opcode],
285                        condition, s_bit? "s" : "");
286                    if (arm_dpi_uses_d[secondary_opcode])
287                            debug("%s,", arm_regname[r12]);
288                    if (arm_dpi_uses_n[secondary_opcode])
289                            debug("%s,", arm_regname[r16]);
290    
291                    if (main_opcode & 2) {
292                            /*  Immediate form:  */
293                            int r = (iw >> 7) & 30;
294                            uint32_t b = iw & 0xff;
295                            while (r-- > 0)
296                                    b = (b >> 1) | ((b & 1) << 31);
297                            if (b < 15)
298                                    debug("#%i", b);
299                            else
300                                    debug("#0x%x", b);
301                    } else {
302                            /*  Register form:  */
303                            int t = (iw >> 4) & 7;
304                            int c = (iw >> 7) & 31;
305                            debug("%s", arm_regname[iw & 15]);
306                            switch (t) {
307                            case 0: if (c != 0)
308                                            debug(" LSL #%i", c);
309                                    break;
310                            case 1: debug(" LSL %s", arm_regname[c >> 1]);
311                                    break;
312                            case 2: debug(" LSR #%i", c? c : 32);
313                                    break;
314                            case 3: debug(" LSR %s", arm_regname[c >> 1]);
315                                    break;
316                            case 4: debug(" ASR #%i", c? c : 32);
317                                    break;
318                            case 5: debug(" ASR %s", arm_regname[c >> 1]);
319                                    break;
320                            case 6: if (c != 0)
321                                            debug(" ROR #%i", c);
322                                    else
323                                            debug(" RRX");
324                                    break;
325                            case 7: debug(" ROR %s", arm_regname[c >> 1]);
326                                    break;
327                            }
328                    }
329                    debug("\n");
330                    break;
331            case 0x4:                               /*  Single Data Transfer  */
332            case 0x5:
333            case 0x6:
334            case 0x7:
335                    /*
336                     *  See (1):
337                     *  xxxx010P UBWLnnnn ddddoooo oooooooo  Immediate form
338                     *  xxxx011P UBWLnnnn ddddcccc ctt0mmmm  Register form
339                     */
340                    p_bit = main_opcode & 1;
341                    if (main_opcode >= 6 && iw & 0x10) {
342                            debug("TODO: single data transf. but 0x10\n");
343                            break;
344                    }
345                    debug("%s%s%s", l_bit? "ldr" : "str",
346                        condition, b_bit? "b" : "");
347                    if (!p_bit && w_bit)
348                            debug("t");
349                    debug("\t%s,[%s", arm_regname[r12], arm_regname[r16]);
350                    if (main_opcode < 6) {
351                            /*  Immediate form:  */
352                            uint32_t imm = iw & 0xfff;
353                            if (!p_bit)
354                                    debug("]");
355                            if (imm != 0)
356                                    debug(",#%s%i", u_bit? "" : "-", imm);
357                            if (p_bit)
358                                    debug("]");
359                    } else {
360                            debug(" TODO: REG-form]");
361                    }
362                    debug("%s\n", (p_bit && w_bit)? "!" : "");
363                    break;
364            case 0x8:                               /*  Block Data Transfer  */
365            case 0x9:
366                    debug("TODO: block data transfer\n");
367                    break;
368            case 0xa:                               /*  B: branch  */
369            case 0xb:                               /*  BL: branch and link  */
370                    debug("b%s%s\t", main_opcode == 0xa? "" : "l", condition);
371                    tmp = (iw & 0x00ffffff) << 2;
372                    if (tmp & 0x02000000)
373                            tmp |= 0xfc000000;
374                    tmp = (int32_t)(dumpaddr + tmp + 8);
375                    debug("0x%x", (int)tmp);
376                    symbol = get_symbol_name(&cpu->machine->symbol_context,
377                        tmp, &offset);
378                    if (symbol != NULL)
379                            debug("\t\t<%s>", symbol);
380                    debug("\n");
381                    break;
382            case 0xc:                               /*  Coprocessor  */
383            case 0xd:                               /*  LDC/STC  */
384                    /*  xxxx110P UNWLnnnn DDDDpppp oooooooo LDC/STC  */
385                    debug("TODO: coprocessor LDC/STC\n");
386                    break;
387            case 0xe:                               /*  CDP (Coprocessor Op)  */
388                    /*                                  or MRC/MCR!
389                     *  According to (1):
390                     *  xxxx1110 oooonnnn ddddpppp qqq0mmmm         CDP
391                     *  xxxx1110 oooLNNNN ddddpppp qqq1MMMM         MRC/MCR
392                     */
393                    if (iw & 0x10) {
394                            debug("%s%s\t",
395                                (iw & 0x00100000)? "mrc" : "mcr", condition);
396                            debug("%i,%i,r%i,cr%i,cr%i,%i",
397                                (int)((iw >> 8) & 15), (int)((iw >>21) & 7),
398                                (int)((iw >>12) & 15), (int)((iw >>16) & 15),
399                                (int)((iw >> 0) & 15), (int)((iw >> 5) & 7));
400                    } else {
401                            debug("cdp%s\t", condition);
402                            debug("%i,%i,cr%i,cr%i,cr%i",
403                                (int)((iw >> 8) & 15),
404                                (int)((iw >>20) & 15),
405                                (int)((iw >>12) & 15),
406                                (int)((iw >>16) & 15),
407                                (int)((iw >> 0) & 15));
408                            if ((iw >> 5) & 7)
409                                    debug(",0x%x", (int)((iw >> 5) & 7));
410                    }
411                    debug("\n");
412                    break;
413            case 0xf:                               /*  SWI  */
414                    debug("swi%s\t", condition);
415                    debug("0x%x\n", (int)(iw & 0x00ffffff));
416                    break;
417            default:debug("UNIMPLEMENTED\n");
418            }
419    
420          return sizeof(uint32_t);          return sizeof(uint32_t);
421  }  }
422    
423    
424    /*
425     *  arm_create_or_reset_tc():
426     *
427     *  Create the translation cache in memory (ie allocate memory for it), if
428     *  necessary, and then reset it to an initial state.
429     */
430    static void arm_create_or_reset_tc(struct cpu *cpu)
431    {
432            if (cpu->cd.arm.translation_cache == NULL) {
433                    cpu->cd.arm.translation_cache = malloc(
434                        ARM_TRANSLATION_CACHE_SIZE + ARM_TRANSLATION_CACHE_MARGIN);
435                    if (cpu->cd.arm.translation_cache == NULL) {
436                            fprintf(stderr, "arm_create_or_reset_tc(): out of "
437                                "memory when allocating the translation cache\n");
438                            exit(1);
439                    }
440            }
441    
442            /*  Create an empty table at the beginning of the translation cache:  */
443            memset(cpu->cd.arm.translation_cache, 0, sizeof(uint32_t) *
444                N_BASE_TABLE_ENTRIES);
445    
446            cpu->cd.arm.translation_cache_cur_ofs =
447                N_BASE_TABLE_ENTRIES * sizeof(uint32_t);
448    }
449    
450    
451    /*
452     *  arm_tc_allocate_default_page():
453     *
454     *  Create a default page (with just pointers to instr(to_be_translated)
455     *  at cpu->cd.arm.translation_cache_cur_ofs.
456     */
457    /*  forward declaration of to_be_translated and end_of_page:  */
458    static void instr(to_be_translated)(struct cpu *,struct arm_instr_call *);
459    static void instr(end_of_page)(struct cpu *,struct arm_instr_call *);
460    static void arm_tc_allocate_default_page(struct cpu *cpu, uint32_t physaddr)
461    {
462            struct arm_tc_physpage *ppp;
463            int i;
464    
465            /*  Create the physpage header:  */
466            ppp = (struct arm_tc_physpage *)(cpu->cd.arm.translation_cache
467                + cpu->cd.arm.translation_cache_cur_ofs);
468            ppp->next_ofs = 0;
469            ppp->physaddr = physaddr;
470    
471            for (i=0; i<IC_ENTRIES_PER_PAGE; i++)
472                    ppp->ics[i].f = instr(to_be_translated);
473    
474            ppp->ics[IC_ENTRIES_PER_PAGE].f = instr(end_of_page);
475    
476            cpu->cd.arm.translation_cache_cur_ofs +=
477                sizeof(struct arm_tc_physpage);
478    }
479    
480    
481  #define MEMORY_RW       arm_memory_rw  #define MEMORY_RW       arm_memory_rw
482  #define MEM_ARM  #define MEM_ARM
483  #include "memory_rw.c"  #include "memory_rw.c"
# Line 199  int arm_cpu_disassemble_instr(struct cpu Line 485  int arm_cpu_disassemble_instr(struct cpu
485  #undef MEMORY_RW  #undef MEMORY_RW
486    
487    
488    #include "cpu_arm_instr.c"
489    
490    
491    /*
492     *  arm_cpu_run_instr():
493     *
494     *  Execute one or more instructions on a specific CPU.
495     *
496     *  Return value is the number of instructions executed during this call,
497     *  0 if no instructions were executed.
498     */
499    int arm_cpu_run_instr(struct emul *emul, struct cpu *cpu)
500    {
501            /*
502             *  Find the correct translated page in the translation cache,
503             *  and start running code on that page.
504             */
505    
506            uint32_t cached_pc, physaddr, physpage_ofs;
507            int pagenr, table_index, n_instrs, low_pc;
508            uint32_t *physpage_entryp;
509            struct arm_tc_physpage *ppp;
510    
511            if (cpu->cd.arm.translation_cache == NULL || cpu->cd.
512                arm.translation_cache_cur_ofs >= ARM_TRANSLATION_CACHE_SIZE)
513                    arm_create_or_reset_tc(cpu);
514    
515            cached_pc = cpu->cd.arm.r[ARM_PC];
516    
517            physaddr = cached_pc & ~(((IC_ENTRIES_PER_PAGE-1) << 2) | 3);
518            /*  TODO: virtual to physical  */
519    
520            pagenr = ADDR_TO_PAGENR(physaddr);
521            table_index = PAGENR_TO_TABLE_INDEX(pagenr);
522    
523            physpage_entryp = &(((uint32_t *)
524                cpu->cd.arm.translation_cache)[table_index]);
525            physpage_ofs = *physpage_entryp;
526            ppp = NULL;
527    
528            /*  Traverse the physical page chain:  */
529            while (physpage_ofs != 0) {
530                    ppp = (struct arm_tc_physpage *)(cpu->cd.arm.translation_cache
531                        + physpage_ofs);
532                    /*  If we found the page in the cache, then we're done:  */
533                    if (ppp->physaddr == physaddr)
534                            break;
535                    /*  Try the next page in the chain:  */
536                    physpage_ofs = ppp->next_ofs;
537            }
538    
539            /*  If the offset is 0 (or ppp is NULL), then we need to create a
540                new "default" empty translation page.  */
541    
542            if (ppp == NULL) {
543                    fatal("CREATING page %i (physaddr 0x%08x), table index = %i\n",
544                        pagenr, physaddr, table_index);
545                    *physpage_entryp = physpage_ofs =
546                        cpu->cd.arm.translation_cache_cur_ofs;
547    
548                    arm_tc_allocate_default_page(cpu, physaddr);
549    
550                    ppp = (struct arm_tc_physpage *)(cpu->cd.arm.translation_cache
551                        + physpage_ofs);
552            }
553    
554            cpu->cd.arm.cur_physpage = ppp;
555            cpu->cd.arm.cur_ic_page = &ppp->ics[0];
556            cpu->cd.arm.next_ic = cpu->cd.arm.cur_ic_page +
557                PC_TO_IC_ENTRY(cached_pc);
558    
559            /*  printf("cached_pc = 0x%08x  pagenr = %i  table_index = %i, "
560                "physpage_ofs = 0x%08x\n", (int)cached_pc, (int)pagenr,
561                (int)table_index, (int)physpage_ofs);  */
562    
563            cpu->cd.arm.n_translated_instrs = 0;
564            cpu->cd.arm.running_translated = 1;
565    
566            if (single_step || cpu->machine->instruction_trace) {
567                    /*
568                     *  Single-step:
569                     */
570                    struct arm_instr_call *ic = cpu->cd.arm.next_ic ++;
571                    if (cpu->machine->instruction_trace) {
572                            unsigned char instr[4];
573                            if (!cpu->memory_rw(cpu, cpu->mem, cpu->pc, &instr[0],
574                                sizeof(instr), MEM_READ, CACHE_INSTRUCTION)) {
575                                    fatal("arm_cpu_run_instr(): could not read "
576                                        "the instruction\n");
577                            } else
578                                    arm_cpu_disassemble_instr(cpu, instr, 1, 0, 0);
579                    }
580    
581                    /*  When single-stepping, multiple instruction calls cannot
582                        be combined into one. This clears all translations:  */
583                    if (ppp->flags & ARM_COMBINATIONS) {
584                            int i;
585                            for (i=0; i<IC_ENTRIES_PER_PAGE; i++)
586                                    ppp->ics[i].f = instr(to_be_translated);
587                            debug("[ Note: The translation of physical page 0x%08x"
588                                " contained combinations of instructions; these "
589                                "are now flushed because we are single-stepping."
590                                " ]\n", ppp->physaddr);
591                            ppp->flags &= ~ARM_COMBINATIONS;
592                    }
593    
594                    /*  Execute just one instruction:  */
595                    ic->f(cpu, ic);
596                    n_instrs = 1;
597            } else {
598                    /*  Execute multiple instructions:  */
599                    n_instrs = 0;
600                    for (;;) {
601                            struct arm_instr_call *ic;
602                            ic = cpu->cd.arm.next_ic ++; ic->f(cpu, ic);
603                            ic = cpu->cd.arm.next_ic ++; ic->f(cpu, ic);
604                            ic = cpu->cd.arm.next_ic ++; ic->f(cpu, ic);
605                            ic = cpu->cd.arm.next_ic ++; ic->f(cpu, ic);
606                            ic = cpu->cd.arm.next_ic ++; ic->f(cpu, ic);
607                            ic = cpu->cd.arm.next_ic ++; ic->f(cpu, ic);
608                            ic = cpu->cd.arm.next_ic ++; ic->f(cpu, ic);
609                            ic = cpu->cd.arm.next_ic ++; ic->f(cpu, ic);
610    
611                            ic = cpu->cd.arm.next_ic ++; ic->f(cpu, ic);
612                            ic = cpu->cd.arm.next_ic ++; ic->f(cpu, ic);
613                            ic = cpu->cd.arm.next_ic ++; ic->f(cpu, ic);
614                            ic = cpu->cd.arm.next_ic ++; ic->f(cpu, ic);
615                            ic = cpu->cd.arm.next_ic ++; ic->f(cpu, ic);
616                            ic = cpu->cd.arm.next_ic ++; ic->f(cpu, ic);
617                            ic = cpu->cd.arm.next_ic ++; ic->f(cpu, ic);
618                            ic = cpu->cd.arm.next_ic ++; ic->f(cpu, ic);
619    
620                            ic = cpu->cd.arm.next_ic ++; ic->f(cpu, ic);
621                            ic = cpu->cd.arm.next_ic ++; ic->f(cpu, ic);
622                            ic = cpu->cd.arm.next_ic ++; ic->f(cpu, ic);
623                            ic = cpu->cd.arm.next_ic ++; ic->f(cpu, ic);
624                            ic = cpu->cd.arm.next_ic ++; ic->f(cpu, ic);
625                            ic = cpu->cd.arm.next_ic ++; ic->f(cpu, ic);
626                            ic = cpu->cd.arm.next_ic ++; ic->f(cpu, ic);
627                            ic = cpu->cd.arm.next_ic ++; ic->f(cpu, ic);
628    
629                            n_instrs += 24;
630                            if (!cpu->cd.arm.running_translated || single_step ||
631                                n_instrs + cpu->cd.arm.n_translated_instrs >= 8192)
632                                    break;
633                    }
634            }
635    
636    
637            /*
638             *  Update the program counter and return the correct number of
639             *  executed instructions:
640             */
641            low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)
642                cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
643    
644            if (low_pc >= 0 && low_pc < IC_ENTRIES_PER_PAGE) {
645                    cpu->cd.arm.r[ARM_PC] &= ~((IC_ENTRIES_PER_PAGE-1) << 2);
646                    cpu->cd.arm.r[ARM_PC] += (low_pc << 2);
647                    cpu->pc = cpu->cd.arm.r[ARM_PC];
648            } else {
649                    fatal("Outside a page (This is actually ok)\n");
650            }
651    
652            return n_instrs + cpu->cd.arm.n_translated_instrs;
653    }
654    
655    
656    #define CPU_RUN         arm_cpu_run
657    #define CPU_RINSTR      arm_cpu_run_instr
658    #define CPU_RUN_ARM
659    #include "cpu_run.c"
660    #undef CPU_RINSTR
661    #undef CPU_RUN_ARM
662    #undef CPU_RUN
663    
664    
665  /*  /*
666   *  arm_cpu_family_init():   *  arm_cpu_family_init():
667   *   *
668   *  Fill in the cpu_family struct for ARM.   *  This function fills the cpu_family struct with valid data.
669   */   */
670  int arm_cpu_family_init(struct cpu_family *fp)  int arm_cpu_family_init(struct cpu_family *fp)
671  {  {
# Line 211  int arm_cpu_family_init(struct cpu_famil Line 674  int arm_cpu_family_init(struct cpu_famil
674          fp->list_available_types = arm_cpu_list_available_types;          fp->list_available_types = arm_cpu_list_available_types;
675          fp->register_match = arm_cpu_register_match;          fp->register_match = arm_cpu_register_match;
676          fp->disassemble_instr = arm_cpu_disassemble_instr;          fp->disassemble_instr = arm_cpu_disassemble_instr;
677          /*  fp->register_dump = arm_cpu_register_dump;  */          fp->register_dump = arm_cpu_register_dump;
678          /*  fp->run = arm_cpu_run;  */          fp->run = arm_cpu_run;
679          fp->dumpinfo = arm_cpu_dumpinfo;          fp->dumpinfo = arm_cpu_dumpinfo;
680          /*  fp->show_full_statistics = arm_cpu_show_full_statistics;  */          /*  fp->show_full_statistics = arm_cpu_show_full_statistics;  */
681          /*  fp->tlbdump = arm_cpu_tlbdump;  */          /*  fp->tlbdump = arm_cpu_tlbdump;  */

Legend:
Removed from v.6  
changed lines
  Added in v.10

  ViewVC Help
Powered by ViewVC 1.1.26