/[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 12 by dpavlin, Mon Oct 8 16:18:38 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.57 2005/08/12 20:20:28 debug Exp $
29   *   *
30   *  ARM CPU emulation.   *  ARM CPU emulation.
31   *   *
32   *  TODO: This is just a dummy so far.   *  Sources of information refered to in cpu_arm*.c:
33     *
34     *      (1)  http://www.pinknoise.demon.co.uk/ARMinstrs/ARMinstrs.html
35   */   */
36    
37  #include <stdio.h>  #include <stdio.h>
# Line 66  int arm_cpu_family_init(struct cpu_famil Line 68  int arm_cpu_family_init(struct cpu_famil
68  #include "memory.h"  #include "memory.h"
69  #include "symbol.h"  #include "symbol.h"
70    
71    #define DYNTRANS_32
72    #include "tmp_arm_head.c"
73    
74    
75  extern volatile int single_step;  /*  ARM symbolic register names and condition strings:  */
76  extern int old_show_trace_tree;    static char *arm_regname[N_ARM_REGS] = ARM_REG_NAMES;
77  extern int old_instruction_trace;  static char *arm_condition_string[16] = ARM_CONDITION_STRINGS;
78  extern int old_quiet_mode;  
79  extern int quiet_mode;  /*  Data Processing Instructions:  */
80    static char *arm_dpiname[16] = ARM_DPI_NAMES;
81    static int arm_dpi_uses_d[16] = { 1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1 };
82    static int arm_dpi_uses_n[16] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0 };
83    
84    
85  /*  /*
86   *  arm_cpu_new():   *  arm_cpu_new():
87   *   *
88   *  Create a new ARM cpu object.   *  Create a new ARM cpu object by filling the CPU struct.
89     *  Return 1 on success, 0 if cpu_type_name isn't a valid ARM processor.
90   */   */
91  struct cpu *arm_cpu_new(struct memory *mem, struct machine *machine,  int arm_cpu_new(struct cpu *cpu, struct memory *mem,
92          int cpu_id, char *cpu_type_name)          struct machine *machine, int cpu_id, char *cpu_type_name)
93  {  {
94          struct cpu *cpu;          if (strcmp(cpu_type_name, "ARM") != 0)
95                    return 0;
96    
97          if (cpu_type_name == NULL || strcmp(cpu_type_name, "ARM") != 0)          cpu->memory_rw = arm_memory_rw;
98                  return NULL;          cpu->update_translation_table = arm_update_translation_table;
99            cpu->invalidate_translation_caches_paddr =
100          cpu = malloc(sizeof(struct cpu));              arm_invalidate_translation_caches_paddr;
101          if (cpu == NULL) {          cpu->invalidate_code_translation_caches =
102                  fprintf(stderr, "out of memory\n");              arm_invalidate_code_translation_caches;
103                  exit(1);          cpu->is_32bit = 1;
         }  
104    
105          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;  
106    
107          /*  Only show name and caches etc for CPU nr 0 (in SMP machines):  */          /*  Only show name and caches etc for CPU nr 0:  */
108          if (cpu_id == 0) {          if (cpu_id == 0) {
109                  debug("%s", cpu->name);                  debug("%s", cpu->name);
110          }          }
111    
112          return cpu;          return 1;
113  }  }
114    
115    
# Line 117  struct cpu *arm_cpu_new(struct memory *m Line 118  struct cpu *arm_cpu_new(struct memory *m
118   */   */
119  void arm_cpu_dumpinfo(struct cpu *cpu)  void arm_cpu_dumpinfo(struct cpu *cpu)
120  {  {
         debug("\n");  
   
121          /*  TODO  */          /*  TODO  */
122            debug("\n");
123  }  }
124    
125    
# Line 142  void arm_cpu_list_available_types(void) Line 142  void arm_cpu_list_available_types(void)
142  void arm_cpu_register_match(struct machine *m, char *name,  void arm_cpu_register_match(struct machine *m, char *name,
143          int writeflag, uint64_t *valuep, int *match_register)          int writeflag, uint64_t *valuep, int *match_register)
144  {  {
145          int cpunr = 0;          int i, cpunr = 0;
146    
147          /*  CPU number:  */          /*  CPU number:  */
148    
149          /*  TODO  */          /*  TODO  */
150    
151          /*  Register name:  */          /*  Register names:  */
152          if (strcasecmp(name, "pc") == 0) {          for (i=0; i<N_ARM_REGS; i++) {
153                  if (writeflag) {                  if (strcasecmp(name, arm_regname[i]) == 0) {
154                          m->cpus[cpunr]->pc = *valuep;                          if (writeflag) {
155                  } else                                  m->cpus[cpunr]->cd.arm.r[i] = *valuep;
156                          *valuep = m->cpus[cpunr]->pc;                                  if (i == ARM_PC)
157                  *match_register = 1;                                          m->cpus[cpunr]->pc = *valuep;
158                            } else
159                                    *valuep = m->cpus[cpunr]->cd.arm.r[i];
160                            *match_register = 1;
161                    }
162            }
163    }
164    
165    
166    /*
167     *  arm_cpu_register_dump():
168     *
169     *  Dump cpu registers in a relatively readable format.
170     *  
171     *  gprs: set to non-zero to dump GPRs and some special-purpose registers.
172     *  coprocs: set bit 0..3 to dump registers in coproc 0..3.
173     */
174    void arm_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
175    {
176            char *symbol;
177            uint64_t offset;
178            int mode = cpu->cd.arm.flags & ARM_FLAG_MODE;
179            int i, x = cpu->cpu_id;
180    
181            if (gprs) {
182                    symbol = get_symbol_name(&cpu->machine->symbol_context,
183                        cpu->cd.arm.r[ARM_PC], &offset);
184                    debug("cpu%i:  flags = ", x);
185                    debug("%s%s%s%s%s%s",
186                        (cpu->cd.arm.flags & ARM_FLAG_N)? "N" : "n",
187                        (cpu->cd.arm.flags & ARM_FLAG_Z)? "Z" : "z",
188                        (cpu->cd.arm.flags & ARM_FLAG_C)? "C" : "c",
189                        (cpu->cd.arm.flags & ARM_FLAG_V)? "V" : "v",
190                        (cpu->cd.arm.flags & ARM_FLAG_I)? "I" : "i",
191                        (cpu->cd.arm.flags & ARM_FLAG_F)? "F" : "f");
192                    if (mode < ARM_MODE_USR32)
193                            debug("   pc =  0x%07x",
194                                (int)(cpu->cd.arm.r[ARM_PC] & 0x03ffffff));
195                    else
196                            debug("   pc = 0x%08x", (int)cpu->cd.arm.r[ARM_PC]);
197    
198                    /*  TODO: Flags  */
199    
200                    debug("  <%s>\n", symbol != NULL? symbol : " no symbol ");
201    
202                    for (i=0; i<N_ARM_REGS; i++) {
203                            if ((i % 4) == 0)
204                                    debug("cpu%i:", x);
205                            if (i != ARM_PC)
206                                    debug("  %s = 0x%08x", arm_regname[i],
207                                        (int)cpu->cd.arm.r[i]);
208                            if ((i % 4) == 3)
209                                    debug("\n");
210                    }
211          }          }
212    }
213    
214    
215    /*
216     *  arm_cpu_show_full_statistics():
217     *
218     *  Show detailed statistics on opcode usage on each cpu.
219     */
220    void arm_cpu_show_full_statistics(struct machine *m)
221    {
222            fatal("arm_cpu_show_full_statistics(): TODO\n");
223    }
224    
225    
226    /*
227     *  arm_cpu_tlbdump():
228     *
229     *  Called from the debugger to dump the TLB in a readable format.
230     *  x is the cpu number to dump, or -1 to dump all CPUs.
231     *
232     *  If rawflag is nonzero, then the TLB contents isn't formated nicely,
233     *  just dumped.
234     */
235    void arm_cpu_tlbdump(struct machine *m, int x, int rawflag)
236    {
237            fatal("arm_cpu_tlbdump(): TODO\n");
238    }
239    
240    
241    /*
242     *  arm_cpu_interrupt():
243     */
244    int arm_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
245    {
246            fatal("arm_cpu_interrupt(): TODO\n");
247            return 0;
248    }
249    
250          /*  TODO: _LOTS_ of stuff.  */  
251    /*
252     *  arm_cpu_interrupt_ack():
253     */
254    int arm_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
255    {
256            /*  fatal("arm_cpu_interrupt_ack(): TODO\n");  */
257            return 0;
258  }  }
259    
260    
# Line 173  void arm_cpu_register_match(struct machi Line 270  void arm_cpu_register_match(struct machi
270   *  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
271   *  cpu->pc for relative addresses.   *  cpu->pc for relative addresses.
272   */                       */                    
273  int arm_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr,  int arm_cpu_disassemble_instr(struct cpu *cpu, unsigned char *ib,
274          int running, uint64_t dumpaddr, int bintrans)          int running, uint64_t dumpaddr, int bintrans)
275  {  {
276          uint32_t iw;          uint32_t iw, tmp;
277            int main_opcode, secondary_opcode, s_bit, r16, r12, r8;
278            int i, n, p_bit, u_bit, b_bit, w_bit, l_bit;
279            char *symbol, *condition;
280            uint64_t offset;
281    
282          if (running)          if (running)
283                  dumpaddr = cpu->pc;                  dumpaddr = cpu->pc;
284    
285            symbol = get_symbol_name(&cpu->machine->symbol_context,
286                dumpaddr, &offset);
287            if (symbol != NULL && offset == 0)
288                    debug("<%s>\n", symbol);
289    
290            if (cpu->machine->ncpus > 1 && running)
291                    debug("cpu%i:\t", cpu->cpu_id);
292    
293          debug("%08x:  ", (int)dumpaddr);          debug("%08x:  ", (int)dumpaddr);
294    
295          iw = instr[0] + (instr[1] << 8) + (instr[2] << 16) + (instr[3] << 24);          if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
296                    iw = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24);
297            else
298                    iw = ib[3] + (ib[2]<<8) + (ib[1]<<16) + (ib[0]<<24);
299          debug("%08x\t", (int)iw);          debug("%08x\t", (int)iw);
300    
301          debug("arm_cpu_disassemble_instr(): TODO\n");          condition = arm_condition_string[iw >> 28];
302            main_opcode = (iw >> 24) & 15;
303            secondary_opcode = (iw >> 21) & 15;
304            u_bit = (iw >> 23) & 1;
305            b_bit = (iw >> 22) & 1;
306            w_bit = (iw >> 21) & 1;
307            s_bit = l_bit = (iw >> 20) & 1;
308            r16 = (iw >> 16) & 15;
309            r12 = (iw >> 12) & 15;
310            r8 = (iw >> 8) & 15;
311    
312            switch (main_opcode) {
313            case 0x0:
314            case 0x1:
315            case 0x2:
316            case 0x3:
317                    /*
318                     *  See (1):
319                     *  xxxx000a aaaSnnnn ddddcccc ctttmmmm  Register form
320                     *  xxxx001a aaaSnnnn ddddrrrr bbbbbbbb  Immediate form
321                     */
322                    if (iw & 0x80 && !(main_opcode & 2) && iw & 0x10) {
323                            debug("UNIMPLEMENTED reg (c!=0), t odd\n");
324                            break;
325                    }
326    
327                    debug("%s%s%s\t", arm_dpiname[secondary_opcode],
328                        condition, s_bit? "s" : "");
329                    if (arm_dpi_uses_d[secondary_opcode])
330                            debug("%s,", arm_regname[r12]);
331                    if (arm_dpi_uses_n[secondary_opcode])
332                            debug("%s,", arm_regname[r16]);
333    
334                    if (main_opcode & 2) {
335                            /*  Immediate form:  */
336                            int r = (iw >> 7) & 30;
337                            uint32_t b = iw & 0xff;
338                            while (r-- > 0)
339                                    b = (b >> 1) | ((b & 1) << 31);
340                            if (b < 15)
341                                    debug("#%i", b);
342                            else
343                                    debug("#0x%x", b);
344                    } else {
345                            /*  Register form:  */
346                            int t = (iw >> 4) & 7;
347                            int c = (iw >> 7) & 31;
348                            debug("%s", arm_regname[iw & 15]);
349                            switch (t) {
350                            case 0: if (c != 0)
351                                            debug(", lsl #%i", c);
352                                    break;
353                            case 1: debug(", lsl %s", arm_regname[c >> 1]);
354                                    break;
355                            case 2: debug(", lsr #%i", c? c : 32);
356                                    break;
357                            case 3: debug(", lsr %s", arm_regname[c >> 1]);
358                                    break;
359                            case 4: debug(", asr #%i", c? c : 32);
360                                    break;
361                            case 5: debug(", asr %s", arm_regname[c >> 1]);
362                                    break;
363                            case 6: if (c != 0)
364                                            debug(", ror #%i", c);
365                                    else
366                                            debug(", rrx");
367                                    break;
368                            case 7: debug(", ror %s", arm_regname[c >> 1]);
369                                    break;
370                            }
371                    }
372                    debug("\n");
373                    break;
374            case 0x4:                               /*  Single Data Transfer  */
375            case 0x5:
376            case 0x6:
377            case 0x7:
378                    /*
379                     *  See (1):
380                     *  xxxx010P UBWLnnnn ddddoooo oooooooo  Immediate form
381                     *  xxxx011P UBWLnnnn ddddcccc ctt0mmmm  Register form
382                     */
383                    p_bit = main_opcode & 1;
384                    if (main_opcode >= 6 && iw & 0x10) {
385                            debug("TODO: single data transf. but 0x10\n");
386                            break;
387                    }
388                    debug("%s%s%s", l_bit? "ldr" : "str",
389                        condition, b_bit? "b" : "");
390                    if (!p_bit && w_bit)
391                            debug("t");
392                    debug("\t%s,[%s", arm_regname[r12], arm_regname[r16]);
393                    if (main_opcode < 6) {
394                            /*  Immediate form:  */
395                            uint32_t imm = iw & 0xfff;
396                            if (!p_bit)
397                                    debug("]");
398                            if (imm != 0)
399                                    debug(",#%s%i", u_bit? "" : "-", imm);
400                            if (p_bit)
401                                    debug("]");
402                    } else {
403                            debug(" TODO: REG-form]");
404                    }
405                    debug("%s\n", (p_bit && w_bit)? "!" : "");
406                    break;
407            case 0x8:                               /*  Block Data Transfer  */
408            case 0x9:
409                    /*  See (1):  xxxx100P USWLnnnn llllllll llllllll  */
410                    p_bit = main_opcode & 1;
411                    s_bit = b_bit;
412                    debug("%s%s", l_bit? "ldm" : "stm", condition);
413                    switch (u_bit * 2 + p_bit) {
414                    case 0: debug("da"); break;
415                    case 1: debug("db"); break;
416                    case 2: debug("ia"); break;
417                    case 3: debug("ib"); break;
418                    }
419                    debug("\t%s", arm_regname[r16]);
420                    if (w_bit)
421                            debug("!");
422                    debug(",{");
423                    n = 0;
424                    for (i=0; i<16; i++)
425                            if ((iw >> i) & 1) {
426                                    debug("%s%s", (n > 0)? ",":"", arm_regname[i]);
427                                    n++;
428                            }
429                    debug("}");
430                    if (s_bit)
431                            debug("^");
432                    debug("\n");
433                    break;
434            case 0xa:                               /*  B: branch  */
435            case 0xb:                               /*  BL: branch and link  */
436                    debug("b%s%s\t", main_opcode == 0xa? "" : "l", condition);
437                    tmp = (iw & 0x00ffffff) << 2;
438                    if (tmp & 0x02000000)
439                            tmp |= 0xfc000000;
440                    tmp = (int32_t)(dumpaddr + tmp + 8);
441                    debug("0x%x", (int)tmp);
442                    symbol = get_symbol_name(&cpu->machine->symbol_context,
443                        tmp, &offset);
444                    if (symbol != NULL)
445                            debug("\t\t<%s>", symbol);
446                    debug("\n");
447                    break;
448            case 0xc:                               /*  Coprocessor  */
449            case 0xd:                               /*  LDC/STC  */
450                    /*  xxxx110P UNWLnnnn DDDDpppp oooooooo LDC/STC  */
451                    debug("TODO: coprocessor LDC/STC\n");
452                    break;
453            case 0xe:                               /*  CDP (Coprocessor Op)  */
454                    /*                                  or MRC/MCR!
455                     *  According to (1):
456                     *  xxxx1110 oooonnnn ddddpppp qqq0mmmm         CDP
457                     *  xxxx1110 oooLNNNN ddddpppp qqq1MMMM         MRC/MCR
458                     */
459                    if (iw & 0x10) {
460                            debug("%s%s\t",
461                                (iw & 0x00100000)? "mrc" : "mcr", condition);
462                            debug("%i,%i,r%i,cr%i,cr%i,%i",
463                                (int)((iw >> 8) & 15), (int)((iw >>21) & 7),
464                                (int)((iw >>12) & 15), (int)((iw >>16) & 15),
465                                (int)((iw >> 0) & 15), (int)((iw >> 5) & 7));
466                    } else {
467                            debug("cdp%s\t", condition);
468                            debug("%i,%i,cr%i,cr%i,cr%i",
469                                (int)((iw >> 8) & 15),
470                                (int)((iw >>20) & 15),
471                                (int)((iw >>12) & 15),
472                                (int)((iw >>16) & 15),
473                                (int)((iw >> 0) & 15));
474                            if ((iw >> 5) & 7)
475                                    debug(",0x%x", (int)((iw >> 5) & 7));
476                    }
477                    debug("\n");
478                    break;
479            case 0xf:                               /*  SWI  */
480                    debug("swi%s\t", condition);
481                    debug("0x%x\n", (int)(iw & 0x00ffffff));
482                    break;
483            default:debug("UNIMPLEMENTED\n");
484            }
485    
486          return sizeof(uint32_t);          return sizeof(uint32_t);
487  }  }
488    
489    
490  #define MEMORY_RW       arm_memory_rw  #include "tmp_arm_tail.c"
 #define MEM_ARM  
 #include "memory_rw.c"  
 #undef MEM_ARM  
 #undef MEMORY_RW  
   
491    
 /*  
  *  arm_cpu_family_init():  
  *  
  *  Fill in the cpu_family struct for ARM.  
  */  
 int arm_cpu_family_init(struct cpu_family *fp)  
 {  
         fp->name = "ARM";  
         fp->cpu_new = arm_cpu_new;  
         fp->list_available_types = arm_cpu_list_available_types;  
         fp->register_match = arm_cpu_register_match;  
         fp->disassemble_instr = arm_cpu_disassemble_instr;  
         /*  fp->register_dump = arm_cpu_register_dump;  */  
         /*  fp->run = arm_cpu_run;  */  
         fp->dumpinfo = arm_cpu_dumpinfo;  
         /*  fp->show_full_statistics = arm_cpu_show_full_statistics;  */  
         /*  fp->tlbdump = arm_cpu_tlbdump;  */  
         /*  fp->interrupt = arm_cpu_interrupt;  */  
         /*  fp->interrupt_ack = arm_cpu_interrupt_ack;  */  
         return 1;  
 }  
492    
493  #endif  /*  ENABLE_ARM  */  #endif  /*  ENABLE_ARM  */

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

  ViewVC Help
Powered by ViewVC 1.1.26