/[gxemul]/trunk/src/cpu_arm_instr.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_instr.c

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

revision 11 by dpavlin, Mon Oct 8 16:18:27 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_instr.c,v 1.20 2005/06/27 09:20:19 debug Exp $   *  $Id: cpu_arm_instr.c,v 1.51 2005/08/16 05:37:10 debug Exp $
29   *   *
30   *  ARM instructions.   *  ARM instructions.
31   *   *
32   *  Individual functions should keep track of cpu->cd.arm.n_translated_instrs.   *  Individual functions should keep track of cpu->n_translated_instrs.
33   *  (If no instruction was executed, then it should be decreased. If, say, 4   *  (If no instruction was executed, then it should be decreased. If, say, 4
34   *  instructions were combined into one function and executed, then it should   *  instructions were combined into one function and executed, then it should
35   *  be increased by 3.)   *  be increased by 3.)
# Line 53  Line 53 
53   *  all of these functions.   *  all of these functions.
54   */   */
55    
 #define X(n) void arm_instr_ ## n(struct cpu *cpu, \  
         struct arm_instr_call *ic)  
   
56  #define Y(n) void arm_instr_ ## n ## __eq(struct cpu *cpu,              \  #define Y(n) void arm_instr_ ## n ## __eq(struct cpu *cpu,              \
57                          struct arm_instr_call *ic)                      \                          struct arm_instr_call *ic)                      \
58          {  if (cpu->cd.arm.flags & ARM_FLAG_Z)                          \          {  if (cpu->cd.arm.flags & ARM_FLAG_Z)                          \
# Line 134  Line 131 
131  #define cond_instr(n)   ( arm_cond_instr_ ## n  [condition_code] )  #define cond_instr(n)   ( arm_cond_instr_ ## n  [condition_code] )
132    
133    
 /*  This is for marking a physical page as containing combined instructions:  */  
 #define combined        (cpu->cd.arm.cur_physpage->flags |= ARM_COMBINATIONS)  
   
   
 void arm_translate_instruction(struct cpu *cpu, struct arm_instr_call *ic);  
   
   
 /*  
  *  nothing:  Do nothing.  
  *  
  *  The difference between this function and the "nop" instruction is that  
  *  this function does not increase the program counter or the number of  
  *  translated instructions.  It is used to "get out" of running in translated  
  *  mode.  
  */  
 X(nothing)  
 {  
         cpu->cd.arm.running_translated = 0;  
         cpu->cd.arm.n_translated_instrs --;  
         cpu->cd.arm.next_ic --;  
 }  
   
   
 static struct arm_instr_call nothing_call = { instr(nothing), {0,0,0} };  
   
   
134  /*****************************************************************************/  /*****************************************************************************/
135    
136    
# Line 178  X(nop) Line 149  X(nop)
149   */   */
150  X(b)  X(b)
151  {  {
152          int low_pc;          uint32_t low_pc;
         uint32_t old_pc;  
   
         /*  fatal("b: arg[0] = 0x%08x, pc=0x%08x\n", ic->arg[0], cpu->pc);  */  
153    
154          /*  Calculate new PC from this instruction + arg[0]  */          /*  Calculate new PC from this instruction + arg[0]  */
155          low_pc = ((size_t)ic - (size_t)          low_pc = ((size_t)ic - (size_t)
156              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
157          cpu->cd.arm.r[ARM_PC] &= ~((IC_ENTRIES_PER_PAGE-1) << 2);          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << 2);
158          cpu->cd.arm.r[ARM_PC] += (low_pc << 2);          cpu->cd.arm.r[ARM_PC] += (low_pc << 2);
         old_pc = cpu->cd.arm.r[ARM_PC];  
         /*  fatal("b: 3: old_pc=0x%08x\n", old_pc);  */  
159          cpu->cd.arm.r[ARM_PC] += (int32_t)ic->arg[0];          cpu->cd.arm.r[ARM_PC] += (int32_t)ic->arg[0];
160          cpu->pc = cpu->cd.arm.r[ARM_PC];          cpu->pc = cpu->cd.arm.r[ARM_PC];
         /*  fatal("b: 2: pc=0x%08x\n", cpu->pc);  */  
161    
162          fatal("b: different page! TODO\n");          /*  Find the new physical page and update the translation pointers:  */
163          exit(1);          arm_pc_to_pointers(cpu);
164  }  }
165  Y(b)  Y(b)
166    
# Line 216  Y(b_samepage) Line 181  Y(b_samepage)
181   *  bl:  Branch and Link (to a different translated page)   *  bl:  Branch and Link (to a different translated page)
182   *   *
183   *  arg[0] = relative address   *  arg[0] = relative address
  *  
  *  TODO: Implement this.  
  *  TODO: How about function call trace?  
184   */   */
185  X(bl)  X(bl)
186  {  {
187          fatal("bl different page: TODO\n");          uint32_t lr, low_pc;
188          exit(1);  
189            /*  Figure out what the return (link) address will be:  */
190            low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)
191                cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
192            lr = cpu->cd.arm.r[ARM_PC];
193            lr &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << 2);
194            lr += (low_pc << 2);
195    
196            /*  Link:  */
197            cpu->cd.arm.r[ARM_LR] = lr;
198    
199            /*  Calculate new PC from this instruction + arg[0]  */
200            cpu->pc = cpu->cd.arm.r[ARM_PC] = lr - 4 + (int32_t)ic->arg[0];
201    
202            /*  Find the new physical page and update the translation pointers:  */
203            arm_pc_to_pointers(cpu);
204  }  }
205  Y(bl)  Y(bl)
206    
207    
208  /*  /*
209     *  bl_trace:  Branch and Link (to a different translated page), with trace
210     *
211     *  Same as for bl.
212     */
213    X(bl_trace)
214    {
215            uint32_t lr, low_pc;
216    
217            /*  Figure out what the return (link) address will be:  */
218            low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)
219                cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
220            lr = cpu->cd.arm.r[ARM_PC];
221            lr &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << 2);
222            lr += (low_pc << 2);
223    
224            /*  Link:  */
225            cpu->cd.arm.r[ARM_LR] = lr;
226    
227            /*  Calculate new PC from this instruction + arg[0]  */
228            cpu->pc = cpu->cd.arm.r[ARM_PC] = lr - 4 + (int32_t)ic->arg[0];
229    
230            cpu_functioncall_trace(cpu, cpu->pc);
231    
232            /*  Find the new physical page and update the translation pointers:  */
233            arm_pc_to_pointers(cpu);
234    }
235    Y(bl_trace)
236    
237    
238    /*
239   *  bl_samepage:  A branch + link within the same page   *  bl_samepage:  A branch + link within the same page
240   *   *
241   *  arg[0] = pointer to new arm_instr_call   *  arg[0] = pointer to new arm_instr_call
  *  
  *  TODO: How about function call trace?  
242   */   */
243  X(bl_samepage)  X(bl_samepage)
244  {  {
# Line 243  X(bl_samepage) Line 248  X(bl_samepage)
248          low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)          low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)
249              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
250          lr = cpu->cd.arm.r[ARM_PC];          lr = cpu->cd.arm.r[ARM_PC];
251          lr &= ~((IC_ENTRIES_PER_PAGE-1) << 2);          lr &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << 2);
252          lr += (low_pc << 2);          lr += (low_pc << 2);
253    
254          /*  Link:  */          /*  Link:  */
# Line 256  Y(bl_samepage) Line 261  Y(bl_samepage)
261    
262    
263  /*  /*
264   *  mov:  Set a 32-bit register to a 32-bit value.   *  bl_samepage_trace:  Branch and Link (to the same page), with trace
265   *   *
266   *  arg[0] = pointer to uint32_t in host memory   *  Same as for bl_samepage.
  *  arg[1] = 32-bit value  
267   */   */
268  X(mov)  X(bl_samepage_trace)
269  {  {
270          *((uint32_t *)ic->arg[0]) = ic->arg[1];          uint32_t tmp_pc, lr, low_pc;
 }  
 Y(mov)  
271    
272            /*  Figure out what the return (link) address will be:  */
273            low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)
274                cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
275            lr = cpu->cd.arm.r[ARM_PC];
276            lr &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << 2);
277            lr += (low_pc << 2);
278    
279  /*          /*  Link:  */
280   *  clear:  Set a 32-bit register to 0. (A "mov" to fixed value zero.)          cpu->cd.arm.r[ARM_LR] = lr;
  *  
  *  arg[0] = pointer to uint32_t in host memory  
  */  
 X(clear)  
 {  
         *((uint32_t *)ic->arg[0]) = 0;  
 }  
 Y(clear)  
281    
282            /*  Branch:  */
283            cpu->cd.arm.next_ic = (struct arm_instr_call *) ic->arg[0];
284    
285  /*          low_pc = ((size_t)cpu->cd.arm.next_ic - (size_t)
286   *  load_byte_imm:  Load an 8-bit byte from emulated memory and store it in              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
287   *                  a 32-bit word in host memory.          tmp_pc = cpu->cd.arm.r[ARM_PC];
288   *          tmp_pc &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << 2);
289   *  arg[0] = pointer to uint32_t in host memory of base address          tmp_pc += (low_pc << 2);
290   *  arg[1] = 32-bit offset          cpu_functioncall_trace(cpu, tmp_pc);
  *  arg[2] = pointer to uint32_t in host memory where to store the value  
  */  
 X(load_byte_imm)  
 {  
         unsigned char data[1];  
         uint32_t addr = *((uint32_t *)ic->arg[0]) + ic->arg[1];  
         if (!cpu->memory_rw(cpu, cpu->mem, addr, data, sizeof(data),  
             MEM_READ, CACHE_DATA)) {  
                 fatal("load failed: TODO\n");  
                 exit(1);  
         }  
         *((uint32_t *)ic->arg[2]) = data[0];  
291  }  }
292  Y(load_byte_imm)  Y(bl_samepage_trace)
293    
294    
295  /*  /*
296   *  load_byte_w_imm:   *  mov_pc:  "mov pc,reg"
  *      Load an 8-bit byte from emulated memory and store it in  
  *      a 32-bit word in host memory, with address writeback.  
297   *   *
298   *  arg[0] = pointer to uint32_t in host memory of base address   *  arg[0] = pointer to uint32_t in host memory of source register
  *  arg[1] = 32-bit offset  
  *  arg[2] = pointer to uint32_t in host memory where to store the value  
299   */   */
300  X(load_byte_w_imm)  X(mov_pc)
301  {  {
302          unsigned char data[1];          uint32_t old_pc = cpu->cd.arm.r[ARM_PC];
303          uint32_t addr = *((uint32_t *)ic->arg[0]) + ic->arg[1];          uint32_t mask_within_page = ((ARM_IC_ENTRIES_PER_PAGE-1) << 2) | 3;
         if (!cpu->memory_rw(cpu, cpu->mem, addr, data, sizeof(data),  
             MEM_READ, CACHE_DATA)) {  
                 fatal("load failed: TODO\n");  
                 exit(1);  
         }  
         *((uint32_t *)ic->arg[2]) = data[0];  
         *((uint32_t *)ic->arg[0]) = addr;  
 }  
 Y(load_byte_w_imm)  
304    
305            /*  Update the PC register:  */
306            cpu->pc = cpu->cd.arm.r[ARM_PC] = *((uint32_t *)ic->arg[0]);
307    
308  /*          /*
309   *  load_byte_wpost_imm:           *  Is this a return to code within the same page? Then there is no
310   *      Load an 8-bit byte from emulated memory and store it in           *  need to update all pointers, just next_ic.
311   *      a 32-bit word in host memory, with address writeback AFTER the load.           */
312   *          if ((old_pc & ~mask_within_page) == (cpu->pc & ~mask_within_page)) {
313   *  arg[0] = pointer to uint32_t in host memory of base address                  cpu->cd.arm.next_ic = cpu->cd.arm.cur_ic_page +
314   *  arg[1] = 32-bit offset                      ((cpu->pc & mask_within_page) >> 2);
315   *  arg[2] = pointer to uint32_t in host memory where to store the value          } else {
316   */                  /*  Find the new physical page and update pointers:  */
317  X(load_byte_wpost_imm)                  arm_pc_to_pointers(cpu);
 {  
         unsigned char data[1];  
         uint32_t addr = *((uint32_t *)ic->arg[0]);  
         if (!cpu->memory_rw(cpu, cpu->mem, addr, data, sizeof(data),  
             MEM_READ, CACHE_DATA)) {  
                 fatal("load failed: TODO\n");  
                 exit(1);  
318          }          }
         *((uint32_t *)ic->arg[2]) = data[0];  
         *((uint32_t *)ic->arg[0]) = addr + ic->arg[1];  
319  }  }
320  Y(load_byte_wpost_imm)  Y(mov_pc)
321    
322    
323  /*  /*
324   *  store_byte_imm:  Load a word from a 32-bit word in host memory, and store   *  ret_trace:  "mov pc,lr" with trace enabled
  *                   the lowest 8 bits of that word at an emulated memory  
  *                   address.  
325   *   *
326   *  arg[0] = pointer to uint32_t in host memory of base address   *  arg[0] = ignored  (similar to mov_pc above)
  *  arg[1] = 32-bit offset  
  *  arg[2] = pointer to uint32_t in host memory where to load the value from  
327   */   */
328  X(store_byte_imm)  X(ret_trace)
329  {  {
330          unsigned char data[1];          uint32_t old_pc = cpu->cd.arm.r[ARM_PC];
331          uint32_t addr = *((uint32_t *)ic->arg[0]) + ic->arg[1];          uint32_t mask_within_page = ((ARM_IC_ENTRIES_PER_PAGE-1) << 2) | 3;
         data[0] = *((uint32_t *)ic->arg[2]);  
         if (!cpu->memory_rw(cpu, cpu->mem, addr, data, sizeof(data),  
             MEM_WRITE, CACHE_DATA)) {  
                 fatal("store failed: TODO\n");  
                 exit(1);  
         }  
 }  
 Y(store_byte_imm)  
332    
333            /*  Update the PC register:  */
334            cpu->pc = cpu->cd.arm.r[ARM_PC] = cpu->cd.arm.r[ARM_LR];
335    
336  /*          cpu_functioncall_trace_return(cpu);
337   *  store_byte_wpost_imm:  
338   *      Load a word from a 32-bit word in host memory, and store          /*
339   *      the lowest 8 bits of that word at an emulated memory address.           *  Is this a return to code within the same page? Then there is no
340   *      Then add the immediate offset to the address, and write back           *  need to update all pointers, just next_ic.
341   *      to the first word.           */
342   *          if ((old_pc & ~mask_within_page) == (cpu->pc & ~mask_within_page)) {
343   *  arg[0] = pointer to uint32_t in host memory of base address                  cpu->cd.arm.next_ic = cpu->cd.arm.cur_ic_page +
344   *  arg[1] = 32-bit offset                      ((cpu->pc & mask_within_page) >> 2);
345   *  arg[2] = pointer to uint32_t in host memory where to load the value from          } else {
346   */                  /*  Find the new physical page and update pointers:  */
347  X(store_byte_wpost_imm)                  arm_pc_to_pointers(cpu);
 {  
         unsigned char data[1];  
         uint32_t addr = *((uint32_t *)ic->arg[0]);  
         data[0] = *((uint32_t *)ic->arg[2]);  
         if (!cpu->memory_rw(cpu, cpu->mem, addr, data, sizeof(data),  
             MEM_WRITE, CACHE_DATA)) {  
                 fatal("store failed: TODO\n");  
                 exit(1);  
348          }          }
         *((uint32_t *)ic->arg[0]) = addr + ic->arg[1];  
349  }  }
350  Y(store_byte_wpost_imm)  Y(ret_trace)
351    
352    
353  /*  /*
354   *  load_word_imm:   *  mov_regreg:
  *      Load a 32-bit word from emulated memory and store it in  
  *      a 32-bit word in host memory.  
355   *   *
356   *  arg[0] = pointer to uint32_t in host memory of base address   *  arg[0] = pointer to uint32_t in host memory of destination register
357   *  arg[1] = 32-bit offset   *  arg[1] = pointer to uint32_t in host memory of source register
  *  arg[2] = pointer to uint32_t in host memory where to store the value  
358   */   */
359  X(load_word_imm)  X(mov_regreg)
360  {  {
361          unsigned char data[sizeof(uint32_t)];          *((uint32_t *)ic->arg[0]) = *((uint32_t *)ic->arg[1]);
         uint32_t addr = *((uint32_t *)ic->arg[0]) + ic->arg[1];  
         if (!cpu->memory_rw(cpu, cpu->mem, addr, data, sizeof(data),  
             MEM_READ, CACHE_DATA)) {  
                 fatal("load word failed: TODO\n");  
                 exit(1);  
         }  
         /*  TODO: Big endian  */  
         *((uint32_t *)ic->arg[2]) = data[0] + (data[1] << 8) +  
             (data[2] << 16) + (data[3] << 24);  
362  }  }
363  Y(load_word_imm)  Y(mov_regreg)
364    
365    
366  /*  /*
367   *  load_word_w_imm:   *  mov:  Set a 32-bit register to a 32-bit value.
  *      Load a 32-bit word from emulated memory and store it in  
  *      a 32-bit word in host memory, with address writeback.  
368   *   *
369   *  arg[0] = pointer to uint32_t in host memory of base address   *  arg[0] = pointer to uint32_t in host memory
370   *  arg[1] = 32-bit offset   *  arg[1] = 32-bit value
  *  arg[2] = pointer to uint32_t in host memory where to store the value  
371   */   */
372  X(load_word_w_imm)  X(mov)
373  {  {
374          unsigned char data[sizeof(uint32_t)];          *((uint32_t *)ic->arg[0]) = ic->arg[1];
         uint32_t addr = *((uint32_t *)ic->arg[0]) + ic->arg[1];  
         if (!cpu->memory_rw(cpu, cpu->mem, addr, data, sizeof(data),  
             MEM_READ, CACHE_DATA)) {  
                 fatal("load word failed: TODO\n");  
                 exit(1);  
         }  
         /*  TODO: Big endian  */  
         *((uint32_t *)ic->arg[2]) = data[0] + (data[1] << 8) +  
             (data[2] << 16) + (data[3] << 24);  
         *((uint32_t *)ic->arg[0]) = addr;  
375  }  }
376  Y(load_word_w_imm)  Y(mov)
377    
378    
379  /*  /*
380   *  store_word_imm:  Load a 32-bit word from host memory and store it   *  clear:  Set a 32-bit register to 0. (A "mov" to fixed value zero.)
  *                   in emulated memory.  
381   *   *
382   *  arg[0] = pointer to uint32_t in host memory of base address   *  arg[0] = pointer to uint32_t in host memory
  *  arg[1] = 32-bit offset  
  *  arg[2] = pointer to uint32_t in host memory where to load the value from.  
383   */   */
384  X(store_word_imm)  X(clear)
385  {  {
386          unsigned char data[sizeof(uint32_t)];          *((uint32_t *)ic->arg[0]) = 0;
         uint32_t addr = *((uint32_t *)ic->arg[0]) + ic->arg[1];  
         uint32_t x = *((uint32_t *)ic->arg[2]);  
         /*  TODO: Big endian  */  
         data[0] = x; data[1] = x >> 8; data[2] = x >> 16; data[3] = x >> 24;  
         if (!cpu->memory_rw(cpu, cpu->mem, addr, data, sizeof(data),  
             MEM_WRITE, CACHE_DATA)) {  
                 fatal("store word failed: TODO\n");  
                 exit(1);  
         }  
387  }  }
388  Y(store_word_imm)  Y(clear)
389    
390    
391    #include "tmp_arm_include.c"
392    
393    
394    #define A__NAME arm_instr_store_w0_byte_u1_p0_imm_fixinc1
395    #define A__NAME__general arm_instr_store_w0_byte_u1_p0_imm_fixinc1__general
396    #define A__B
397    #define A__U
398    #define A__NOCONDITIONS
399    #define A__FIXINC       1
400    #include "cpu_arm_instr_loadstore.c"
401    #undef A__NOCONDITIONS
402    #undef A__B
403    #undef A__U
404    #undef A__NAME__general
405    #undef A__NAME
406    
407    
408  /*  /*
# Line 490  X(load_byte_imm_pcrel) Line 421  X(load_byte_imm_pcrel)
421    
422          low_pc = ((size_t)ic - (size_t)          low_pc = ((size_t)ic - (size_t)
423              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
424          cpu->cd.arm.r[ARM_PC] &= ~((IC_ENTRIES_PER_PAGE-1) << 2);          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << 2);
425          cpu->cd.arm.r[ARM_PC] += (low_pc << 2);          cpu->cd.arm.r[ARM_PC] += (low_pc << 2);
426    
427          addr = cpu->cd.arm.r[ARM_PC] + 8 + ic->arg[1];          addr = cpu->cd.arm.r[ARM_PC] + 8 + ic->arg[1];
# Line 520  X(load_word_imm_pcrel) Line 451  X(load_word_imm_pcrel)
451    
452          low_pc = ((size_t)ic - (size_t)          low_pc = ((size_t)ic - (size_t)
453              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);              cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
454          cpu->cd.arm.r[ARM_PC] &= ~((IC_ENTRIES_PER_PAGE-1) << 2);          cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << 2);
455          cpu->cd.arm.r[ARM_PC] += (low_pc << 2);          cpu->cd.arm.r[ARM_PC] += (low_pc << 2);
456    
457          addr = cpu->cd.arm.r[ARM_PC] + 8 + ic->arg[1];          addr = cpu->cd.arm.r[ARM_PC] + 8 + ic->arg[1];
# Line 537  Y(load_word_imm_pcrel) Line 468  Y(load_word_imm_pcrel)
468    
469    
470  /*  /*
471     *  bdt_load:  Block Data Transfer, Load
472     *
473     *  arg[0] = pointer to uint32_t in host memory, pointing to the base register
474     *  arg[1] = 32-bit instruction word. Most bits are read from this.
475     */
476    X(bdt_load)
477    {
478            unsigned char data[4];
479            uint32_t *np = (uint32_t *)ic->arg[0];
480            uint32_t addr = *np;
481            uint32_t iw = ic->arg[1];  /*  xxxx100P USWLnnnn llllllll llllllll  */
482            int p_bit = iw & 0x01000000;
483            int u_bit = iw & 0x00800000;
484            int s_bit = iw & 0x00400000;
485            int w_bit = iw & 0x00200000;
486            int i;
487    
488            if (s_bit) {
489                    fatal("bdt: TODO: s-bit\n");
490                    exit(1);
491            }
492    
493            for (i=(u_bit? 0 : 15); i>=0 && i<=15; i+=(u_bit? 1 : -1))
494                    if ((iw >> i) & 1) {
495                            /*  Load register i:  */
496                            if (p_bit) {
497                                    if (u_bit)
498                                            addr += sizeof(uint32_t);
499                                    else
500                                            addr -= sizeof(uint32_t);
501                            }
502                            if (!cpu->memory_rw(cpu, cpu->mem, addr, data,
503                                sizeof(data), MEM_READ, CACHE_DATA)) {
504                                    fatal("bdt: load failed: TODO\n");
505                                    exit(1);
506                            }
507                            if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
508                                    cpu->cd.arm.r[i] = data[0] +
509                                        (data[1] << 8) + (data[2] << 16)
510                                        + (data[3] << 24);
511                            } else {
512                                    cpu->cd.arm.r[i] = data[3] +
513                                        (data[2] << 8) + (data[1] << 16)
514                                        + (data[0] << 24);
515                            }
516                            /*  NOTE: Special case:  */
517                            if (i == ARM_PC) {
518                                    cpu->cd.arm.r[ARM_PC] &= ~3;
519                                    cpu->pc = cpu->cd.arm.r[ARM_PC];
520                                    /*  TODO: There is no need to update the
521                                        pointers if this is a return to the
522                                        same page!  */
523                                    /*  Find the new physical page and update the
524                                        translation pointers:  */
525                                    arm_pc_to_pointers(cpu);
526                            }
527                            if (!p_bit) {
528                                    if (u_bit)
529                                            addr += sizeof(uint32_t);
530                                    else
531                                            addr -= sizeof(uint32_t);
532                            }
533                    }
534    
535            if (w_bit)
536                    *np = addr;
537    }
538    Y(bdt_load)
539    
540    
541    /*
542     *  bdt_store:  Block Data Transfer, Store
543     *
544     *  arg[0] = pointer to uint32_t in host memory, pointing to the base register
545     *  arg[1] = 32-bit instruction word. Most bits are read from this.
546     */
547    X(bdt_store)
548    {
549            unsigned char data[4];
550            uint32_t *np = (uint32_t *)ic->arg[0];
551            uint32_t addr = *np;
552            uint32_t iw = ic->arg[1];  /*  xxxx100P USWLnnnn llllllll llllllll  */
553            int p_bit = iw & 0x01000000;
554            int u_bit = iw & 0x00800000;
555            int s_bit = iw & 0x00400000;
556            int w_bit = iw & 0x00200000;
557            int i;
558    
559            if (s_bit) {
560                    fatal("bdt: TODO: s-bit\n");
561                    exit(1);
562            }
563    
564            if (iw & 0x8000) {
565                    /*  Synchronize the program counter:  */
566                    uint32_t low_pc = ((size_t)ic - (size_t)
567                        cpu->cd.arm.cur_ic_page) / sizeof(struct arm_instr_call);
568                    cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << 2);
569                    cpu->cd.arm.r[ARM_PC] += (low_pc << 2);
570                    cpu->pc = cpu->cd.arm.r[ARM_PC];
571            }
572    
573            for (i=(u_bit? 0 : 15); i>=0 && i<=15; i+=(u_bit? 1 : -1))
574                    if ((iw >> i) & 1) {
575                            /*  Store register i:  */
576                            uint32_t value = cpu->cd.arm.r[i];
577                            if (i == ARM_PC)
578                                    value += 12;    /*  TODO: 8 on some ARMs?  */
579                            if (p_bit) {
580                                    if (u_bit)
581                                            addr += sizeof(uint32_t);
582                                    else
583                                            addr -= sizeof(uint32_t);
584                            }
585                            if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
586                                    data[0] = value;
587                                    data[1] = value >> 8;
588                                    data[2] = value >> 16;
589                                    data[3] = value >> 24;
590                            } else {
591                                    data[0] = value >> 24;
592                                    data[1] = value >> 16;
593                                    data[2] = value >> 8;
594                                    data[3] = value;
595                            }
596                            if (!cpu->memory_rw(cpu, cpu->mem, addr, data,
597                                sizeof(data), MEM_WRITE, CACHE_DATA)) {
598                                    fatal("bdt: store failed: TODO\n");
599                                    exit(1);
600                            }
601                            if (!p_bit) {
602                                    if (u_bit)
603                                            addr += sizeof(uint32_t);
604                                    else
605                                            addr -= sizeof(uint32_t);
606                            }
607                    }
608    
609            if (w_bit)
610                    *np = addr;
611    }
612    Y(bdt_store)
613    
614    
615    /*
616   *  cmps:  Compare a 32-bit register to a 32-bit value. (Subtraction.)   *  cmps:  Compare a 32-bit register to a 32-bit value. (Subtraction.)
617   *   *
618   *  arg[0] = pointer to uint32_t in host memory   *  arg[0] = pointer to uint32_t in host memory
# Line 549  X(cmps) Line 625  X(cmps)
625          a = *((uint32_t *)ic->arg[0]);          a = *((uint32_t *)ic->arg[0]);
626          b = ic->arg[1];          b = ic->arg[1];
627    
         c = a - b;  
628          cpu->cd.arm.flags &=          cpu->cd.arm.flags &=
629              ~(ARM_FLAG_Z | ARM_FLAG_N | ARM_FLAG_V | ARM_FLAG_C);              ~(ARM_FLAG_Z | ARM_FLAG_N | ARM_FLAG_V | ARM_FLAG_C);
630            c = a - b;
631            if (a > b)
632                    cpu->cd.arm.flags |= ARM_FLAG_C;
633          if (c == 0)          if (c == 0)
634                  cpu->cd.arm.flags |= ARM_FLAG_Z;                  cpu->cd.arm.flags |= ARM_FLAG_Z;
635          if ((int32_t)c < 0) {          if ((int32_t)c < 0) {
# Line 559  X(cmps) Line 637  X(cmps)
637                  n = 1;                  n = 1;
638          } else          } else
639                  n = 0;                  n = 0;
         v = !n;  
640          if ((int32_t)a >= (int32_t)b)          if ((int32_t)a >= (int32_t)b)
641                  v = n;                  v = n;
642            else
643                    v = !n;
644          if (v)          if (v)
645                  cpu->cd.arm.flags |= ARM_FLAG_V;                  cpu->cd.arm.flags |= ARM_FLAG_V;
         if (a > b)  
                 cpu->cd.arm.flags |= ARM_FLAG_C;  
646  }  }
647  Y(cmps)  Y(cmps)
648    
649    
650    #include "cpu_arm_instr_cmps.c"
651    
652    
653  /*  /*
654   *  sub:  Subtract an immediate value from a 32-bit word, and store the   *  sub:  Subtract an immediate value from a 32-bit word, and store the
655   *        result in a 32-bit word.   *        result in a 32-bit word.
# Line 610  X(add_self) Line 690  X(add_self)
690  Y(add_self)  Y(add_self)
691    
692    
693    #include "tmp_arm_include_self.c"
694    
695    
696  /*****************************************************************************/  /*****************************************************************************/
697    
698    
# Line 623  X(mov_2) Line 706  X(mov_2)
706          *((uint32_t *)ic[0].arg[0]) = ic[0].arg[1];          *((uint32_t *)ic[0].arg[0]) = ic[0].arg[1];
707          *((uint32_t *)ic[1].arg[0]) = ic[1].arg[1];          *((uint32_t *)ic[1].arg[0]) = ic[1].arg[1];
708          cpu->cd.arm.next_ic ++;          cpu->cd.arm.next_ic ++;
709          cpu->cd.arm.n_translated_instrs ++;          cpu->n_translated_instrs ++;
710  }  }
711    
712    
713  /*****************************************************************************/  /*
714     *  fill_loop_test:
715     *
716     *  A byte-fill loop. Fills at most one page at a time. If the page was not
717     *  in the host_store table, then the original sequence (beginning with
718     *  cmps r2,#0) is executed instead.
719     *
720     *  Z:cmps r2,#0                ic[0]
721     *    strb rX,[rY],#1           ic[1]
722     *    sub  r2,r2,#1             ic[2]
723     *    bgt  Z                    ic[3]
724     */
725    X(fill_loop_test)
726    {
727            uint32_t addr, a, n, ofs, maxlen;
728            unsigned char *page;
729    
730            addr = *((uint32_t *)ic[1].arg[0]);
731            n = cpu->cd.arm.r[2] + 1;
732            ofs = addr & 0xfff;
733            maxlen = 4096 - ofs;
734            if (n > maxlen)
735                    n = maxlen;
736    
737  X(to_be_translated)          page = cpu->cd.arm.host_store[addr >> 12];
738  {          if (page == NULL) {
739          /*  Translate the instruction...  */                  arm_cmps_0[2](cpu, ic);
740          arm_translate_instruction(cpu, ic);                  return;
741            }
742    
743            /*  printf("x = %x, n = %i\n", *((uint32_t *)ic[1].arg[2]), n);  */
744            memset(page + ofs, *((uint32_t *)ic[1].arg[2]), n);
745    
746            *((uint32_t *)ic[1].arg[0]) = addr + n;
747    
748            cpu->cd.arm.r[2] -= n;
749            cpu->n_translated_instrs += (4 * n);
750    
751            a = cpu->cd.arm.r[2];
752    
753            cpu->cd.arm.flags &=
754                ~(ARM_FLAG_Z | ARM_FLAG_N | ARM_FLAG_V | ARM_FLAG_C);
755            if (a != 0)
756                    cpu->cd.arm.flags |= ARM_FLAG_C;
757            else
758                    cpu->cd.arm.flags |= ARM_FLAG_Z;
759            if ((int32_t)a < 0)
760                    cpu->cd.arm.flags |= ARM_FLAG_N;
761    
762            cpu->n_translated_instrs --;
763    
764          /*  ... and execute it:  */          if ((int32_t)a > 0)
765          ic->f(cpu, ic);                  cpu->cd.arm.next_ic --;
766            else
767                    cpu->cd.arm.next_ic += 3;
768  }  }
769    
770    
771    /*****************************************************************************/
772    
773    
774  X(end_of_page)  X(end_of_page)
775  {  {
776          printf("end_of_page()! pc=0x%08x\n", cpu->cd.arm.r[ARM_PC]);          /*  Update the PC:  (offset 0, but on the next page)  */
777            cpu->cd.arm.r[ARM_PC] &= ~((ARM_IC_ENTRIES_PER_PAGE-1) << 2);
778          /*  Update the PC:  Offset 0, but then go to next page:  */          cpu->cd.arm.r[ARM_PC] += (ARM_IC_ENTRIES_PER_PAGE << 2);
         cpu->cd.arm.r[ARM_PC] &= ~((IC_ENTRIES_PER_PAGE-1) << 2);  
         cpu->cd.arm.r[ARM_PC] += (IC_ENTRIES_PER_PAGE << 2);  
779          cpu->pc = cpu->cd.arm.r[ARM_PC];          cpu->pc = cpu->cd.arm.r[ARM_PC];
780    
781          /*  Find the new (physical) page:  */          /*  Find the new physical page and update the translation pointers:  */
782          /*  TODO  */          arm_pc_to_pointers(cpu);
783    
784          printf("TODO: end_of_page()! new pc=0x%08x\n", cpu->cd.arm.r[ARM_PC]);          /*  end_of_page doesn't count as an executed instruction:  */
785          exit(1);          cpu->n_translated_instrs --;
786  }  }
787    
788    
# Line 665  X(end_of_page) Line 794  X(end_of_page)
794   *   *
795   *  Combine two or more instructions, if possible, into a single function call.   *  Combine two or more instructions, if possible, into a single function call.
796   */   */
797  void arm_combine_instructions(struct cpu *cpu, struct arm_instr_call *ic)  void arm_combine_instructions(struct cpu *cpu, struct arm_instr_call *ic,
798            uint32_t addr)
799  {  {
800          int n_back;          int n_back;
801          n_back = (cpu->pc >> 2) & (IC_ENTRIES_PER_PAGE-1);          n_back = (addr >> 2) & (ARM_IC_ENTRIES_PER_PAGE-1);
802    
803          if (n_back >= 1) {          if (n_back >= 1) {
804                  /*  Double "mov":  */                  /*  Double "mov":  */
# Line 695  void arm_combine_instructions(struct cpu Line 825  void arm_combine_instructions(struct cpu
825                          }                          }
826                  }                  }
827          }          }
828    
829            if (n_back >= 3) {
830                    if (ic[-3].f == arm_cmps_0[2] &&
831                        ic[-2].f == instr(store_w0_byte_u1_p0_imm) &&
832                        ic[-2].arg[1] == 1 &&
833                        ic[-1].f == arm_sub_self_1[2] &&
834                        ic[ 0].f == instr(b_samepage__gt) &&
835                        ic[ 0].arg[0] == (size_t)&ic[-3]) {
836                            ic[-3].f = instr(fill_loop_test);
837                            combined;
838                    }
839            }
840    
841            /*  TODO: Combine forward as well  */
842  }  }
843    
844    
845    /*****************************************************************************/
846    
847    
848  /*  /*
849   *  arm_translate_instruction():   *  arm_instr_to_be_translated():
850   *   *
851   *  Translate an instruction word into an arm_instr_call.   *  Translate an instruction word into an arm_instr_call. ic is filled in with
852     *  valid data for the translated instruction, or a "nothing" instruction if
853     *  there was a translation failure. The newly translated instruction is then
854     *  executed.
855   */   */
856  void arm_translate_instruction(struct cpu *cpu, struct arm_instr_call *ic)  X(to_be_translated)
857  {  {
858          uint32_t addr, low_pc, iword, imm;          uint32_t addr, low_pc, iword, imm;
859            unsigned char *page;
860          unsigned char ib[4];          unsigned char ib[4];
861          int condition_code, main_opcode, secondary_opcode, s_bit, r16, r12, r8;          int condition_code, main_opcode, secondary_opcode, s_bit, r16, r12, r8;
862          int p_bit, u_bit, b_bit, w_bit, l_bit;          int p_bit, u_bit, b_bit, w_bit, l_bit;
863          void (*samepage_function)(struct cpu *, struct arm_instr_call *);          void (*samepage_function)(struct cpu *, struct arm_instr_call *);
864    
865          /*  Make sure that PC is in synch:  */          /*  Figure out the (virtual) address of the instruction:  */
866          low_pc = ((size_t)ic - (size_t)cpu->cd.arm.cur_ic_page)          low_pc = ((size_t)ic - (size_t)cpu->cd.arm.cur_ic_page)
867              / sizeof(struct arm_instr_call);              / sizeof(struct arm_instr_call);
868          cpu->cd.arm.r[ARM_PC] &= ~((IC_ENTRIES_PER_PAGE-1) << 2);          addr = cpu->cd.arm.r[ARM_PC] & ~((ARM_IC_ENTRIES_PER_PAGE-1) <<
869          cpu->cd.arm.r[ARM_PC] += (low_pc << 2);              ARM_INSTR_ALIGNMENT_SHIFT);
870          cpu->pc = cpu->cd.arm.r[ARM_PC];          addr += (low_pc << ARM_INSTR_ALIGNMENT_SHIFT);
871            cpu->pc = cpu->cd.arm.r[ARM_PC] = addr;
872            addr &= ~0x3;
873    
874          /*  Read the instruction word from memory:  */          /*  Read the instruction word from memory:  */
875          addr = cpu->pc & ~0x3;          page = cpu->cd.arm.host_load[addr >> 12];
876    
877          if (!cpu->memory_rw(cpu, cpu->mem, addr, &ib[0],          if (page != NULL) {
878              sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {                  /*  fatal("TRANSLATION HIT!\n");  */
879                  fatal("arm_translate_instruction(): read failed: TODO\n");                  memcpy(ib, page + (addr & 0xfff), sizeof(ib));
880                  goto bad;          } else {
881                    /*  fatal("TRANSLATION MISS!\n");  */
882                    if (!cpu->memory_rw(cpu, cpu->mem, addr, &ib[0],
883                        sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
884                            fatal("to_be_translated(): "
885                                "read failed: TODO\n");
886                            goto bad;
887                    }
888          }          }
889    
890          if (cpu->byte_order == EMUL_LITTLE_ENDIAN)          if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
# Line 735  void arm_translate_instruction(struct cp Line 895  void arm_translate_instruction(struct cp
895          /*  fatal("{ ARM translating pc=0x%08x iword=0x%08x }\n",          /*  fatal("{ ARM translating pc=0x%08x iword=0x%08x }\n",
896              addr, iword);  */              addr, iword);  */
897    
898    
899    #define DYNTRANS_TO_BE_TRANSLATED_HEAD
900    #include "cpu_dyntrans.c"
901    #undef  DYNTRANS_TO_BE_TRANSLATED_HEAD
902    
903    
904          /*  The idea of taking bits 27..24 was found here:          /*  The idea of taking bits 27..24 was found here:
905              http://armphetamine.sourceforge.net/oldinfo.html  */              http://armphetamine.sourceforge.net/oldinfo.html  */
906          condition_code = iword >> 28;          condition_code = iword >> 28;
# Line 766  void arm_translate_instruction(struct cp Line 932  void arm_translate_instruction(struct cp
932          case 0x2:          case 0x2:
933          case 0x3:          case 0x3:
934                  if ((main_opcode & 2) == 0) {                  if ((main_opcode & 2) == 0) {
935                          fatal("REGISTER FORM! TODO\n");                          if ((iword & 0x0ffffff0) == 0x01a0f000) {
936                          goto bad;                                  /*  Hardcoded: mov pc, rX  */
937                                    if ((iword & 15) == ARM_PC) {
938                                            fatal("mov pc,pc?\n");
939                                            goto bad;
940                                    }
941                                    ic->f = cond_instr(mov_pc);
942                                    ic->arg[0] = (size_t)
943                                        (&cpu->cd.arm.r[iword & 15]);
944                                    if ((iword & 15) == ARM_LR &&
945                                        cpu->machine->show_trace_tree)
946                                            ic->f = cond_instr(ret_trace);
947                            } else if ((iword & 0x0fff0ff0) == 0x01a00000) {
948                                    /*  Hardcoded: mov reg,reg  */
949                                    if ((iword & 15) == ARM_PC) {
950                                            fatal("mov reg,pc?\n");
951                                            goto bad;
952                                    }
953                                    ic->f = cond_instr(mov_regreg);
954                                    ic->arg[0] = (size_t)
955                                        (&cpu->cd.arm.r[r12]);
956                                    ic->arg[1] = (size_t)
957                                        (&cpu->cd.arm.r[iword & 15]);
958                            } else {
959                                    fatal("REGISTER FORM! TODO\n");
960                                    goto bad;
961                            }
962                            break;
963                  }                  }
964                  imm = iword & 0xff;                  imm = iword & 0xff;
965                  r8 <<= 1;                  r8 <<= 1;
# Line 777  void arm_translate_instruction(struct cp Line 969  void arm_translate_instruction(struct cp
969                  case 0x2:                               /*  SUB  */                  case 0x2:                               /*  SUB  */
970                  case 0x4:                               /*  ADD  */                  case 0x4:                               /*  ADD  */
971                          if (s_bit) {                          if (s_bit) {
972                                  fatal("sub s_bit: TODO\n");                                  fatal("add/sub s_bit: TODO\n");
973                                    goto bad;
974                            }
975                            if (r12 == ARM_PC || r16 == ARM_PC) {
976                                    fatal("add/sub: PC\n");
977                                  goto bad;                                  goto bad;
978                          }                          }
979                          switch (secondary_opcode) {                          switch (secondary_opcode) {
980                          case 0x2:                          case 0x2:
981                                  if (r12 == r16)                                  ic->f = cond_instr(sub);
982                                    if (r12 == r16) {
983                                          ic->f = cond_instr(sub_self);                                          ic->f = cond_instr(sub_self);
984                                  else                                          if (imm == 1 && r12 != ARM_PC)
985                                          ic->f = cond_instr(sub);                                                  ic->f = arm_sub_self_1[r12];
986                                            if (imm == 4 && r12 != ARM_PC)
987                                                    ic->f = arm_sub_self_4[r12];
988                                    }
989                                  break;                                  break;
990                          case 0x4:                          case 0x4:
991                                  if (r12 == r16)                                  ic->f = cond_instr(add);
992                                    if (r12 == r16) {
993                                          ic->f = cond_instr(add_self);                                          ic->f = cond_instr(add_self);
994                                  else                                          if (imm == 1 && r12 != ARM_PC)
995                                          ic->f = cond_instr(add);                                                  ic->f = arm_add_self_1[r12];
996                                            if (imm == 4 && r12 != ARM_PC)
997                                                    ic->f = arm_add_self_4[r12];
998                                    }
999                                  break;                                  break;
1000                          }                          }
1001                          ic->arg[0] = (size_t)(&cpu->cd.arm.r[r12]);                          ic->arg[0] = (size_t)(&cpu->cd.arm.r[r12]);
# Line 806  void arm_translate_instruction(struct cp Line 1010  void arm_translate_instruction(struct cp
1010                          ic->f = cond_instr(cmps);                          ic->f = cond_instr(cmps);
1011                          ic->arg[0] = (size_t)(&cpu->cd.arm.r[r16]);                          ic->arg[0] = (size_t)(&cpu->cd.arm.r[r16]);
1012                          ic->arg[1] = imm;                          ic->arg[1] = imm;
1013                            if (imm == 0 && r16 != ARM_PC)
1014                                    ic->f = arm_cmps_0[r16];
1015                          break;                          break;
1016                  case 0xd:                               /*  MOV  */                  case 0xd:                               /*  MOV  */
1017                          if (s_bit) {                          if (s_bit) {
# Line 832  void arm_translate_instruction(struct cp Line 1038  void arm_translate_instruction(struct cp
1038          case 0x6:       /*  xxxx011P UBWLnnnn ddddcccc ctt0mmmm  Register  */          case 0x6:       /*  xxxx011P UBWLnnnn ddddcccc ctt0mmmm  Register  */
1039          case 0x7:          case 0x7:
1040                  p_bit = main_opcode & 1;                  p_bit = main_opcode & 1;
1041                    ic->f = load_store_instr[((iword >> 16) & 0x3f0)
1042                        + condition_code];
1043                    imm = iword & 0xfff;
1044                    if (!u_bit)
1045                            imm = (int32_t)0-imm;
1046                  if (main_opcode < 6) {                  if (main_opcode < 6) {
1047                          /*  Immediate:  */                          /*  Immediate:  */
                         imm = iword & 0xfff;  
                         if (!u_bit)  
                                 imm = (int32_t)0-imm;  
1048                          ic->arg[0] = (size_t)(&cpu->cd.arm.r[r16]);                          ic->arg[0] = (size_t)(&cpu->cd.arm.r[r16]);
1049                          ic->arg[1] = (size_t)(imm);                          ic->arg[1] = (size_t)(imm);
1050                          ic->arg[2] = (size_t)(&cpu->cd.arm.r[r12]);                          ic->arg[2] = (size_t)(&cpu->cd.arm.r[r12]);
1051                  }                  }
1052                  if (main_opcode == 4 && b_bit) {                  if (main_opcode == 4 && b_bit) {
1053                          /*  Post-index, immediate:  */                          /*  Post-index, immediate:  */
1054                            if (imm == 1 && !w_bit && l_bit)
1055                                    ic->f = instr(store_w0_byte_u1_p0_imm_fixinc1);
1056                          if (w_bit) {                          if (w_bit) {
1057                                  fatal("load/store: T-bit\n");                                  fatal("load/store: T-bit\n");
1058                                  goto bad;                                  goto bad;
# Line 851  void arm_translate_instruction(struct cp Line 1061  void arm_translate_instruction(struct cp
1061                                  fatal("load/store writeback PC: error\n");                                  fatal("load/store writeback PC: error\n");
1062                                  goto bad;                                  goto bad;
1063                          }                          }
                         if (l_bit)  
                                 ic->f = cond_instr(load_byte_wpost_imm);  
                         else  
                                 ic->f = cond_instr(store_byte_wpost_imm);  
1064                  } else if (main_opcode == 5) {                  } else if (main_opcode == 5) {
1065                          /*  Pre-index, immediate:  */                          /*  Pre-index, immediate:  */
1066                          /*  ldr(b) Rd,[Rn,#imm]  */                          /*  ldr(b) Rd,[Rn,#imm]  */
1067                          if (l_bit) {                          if (l_bit) {
1068                                  if (r12 == ARM_PC)                                  if (r12 == ARM_PC) {
1069                                          fatal("WARNING: ldr to pc register?\n");                                          fatal("WARNING: ldr to pc register?\n");
1070                                  if (w_bit) {                                          goto bad;
                                         ic->f = b_bit?  
                                             cond_instr(load_byte_w_imm) :  
                                             cond_instr(load_word_w_imm);  
                                 } else {  
                                         ic->f = b_bit?  
                                             cond_instr(load_byte_imm) :  
                                             cond_instr(load_word_imm);  
1071                                  }                                  }
1072                                  if (r16 == ARM_PC) {                                  if (r16 == ARM_PC) {
1073                                          if (w_bit) {                                          if (w_bit) {
# Line 880  void arm_translate_instruction(struct cp Line 1079  void arm_translate_instruction(struct cp
1079                                              cond_instr(load_word_imm_pcrel);                                              cond_instr(load_word_imm_pcrel);
1080                                  }                                  }
1081                          } else {                          } else {
                                 if (w_bit) {  
                                         fatal("w bit store etc\n");  
                                         goto bad;  
                                 }  
1082                                  if (r12 == ARM_PC) {                                  if (r12 == ARM_PC) {
1083                                          fatal("TODO: store pc\n");                                          fatal("TODO: store pc\n");
1084                                          goto bad;                                          goto bad;
1085                                  }                                  }
                                 ic->f = b_bit?  
                                     cond_instr(store_byte_imm) :  
                                     cond_instr(store_word_imm);  
1086                                  if (r16 == ARM_PC) {                                  if (r16 == ARM_PC) {
1087                                          fatal("TODO: store pc rel\n");                                          fatal("TODO: store pc rel\n");
1088                                          goto bad;                                          goto bad;
# Line 902  void arm_translate_instruction(struct cp Line 1094  void arm_translate_instruction(struct cp
1094                  }                  }
1095                  break;                  break;
1096    
1097            case 0x8:       /*  Multiple load/store...  (Block data transfer)  */
1098            case 0x9:       /*  xxxx100P USWLnnnn llllllll llllllll  */
1099                    if (l_bit)
1100                            ic->f = cond_instr(bdt_load);
1101                    else
1102                            ic->f = cond_instr(bdt_store);
1103                    ic->arg[0] = (size_t)(&cpu->cd.arm.r[r16]);
1104                    ic->arg[1] = (size_t)iword;
1105                    if (r16 == ARM_PC) {
1106                            fatal("TODO: bdt with PC as base\n");
1107                            goto bad;
1108                    }
1109                    break;
1110    
1111          case 0xa:                                       /*  B: branch  */          case 0xa:                                       /*  B: branch  */
1112          case 0xb:                                       /*  BL: branch+link  */          case 0xb:                                       /*  BL: branch+link  */
1113                  if (main_opcode == 0x0a) {                  if (main_opcode == 0x0a) {
1114                          ic->f = cond_instr(b);                          ic->f = cond_instr(b);
1115                          samepage_function = cond_instr(b_samepage);                          samepage_function = cond_instr(b_samepage);
1116                  } else {                  } else {
1117                          ic->f = cond_instr(bl);                          if (cpu->machine->show_trace_tree) {
1118                          samepage_function = cond_instr(bl_samepage);                                  ic->f = cond_instr(bl_trace);
1119                                    samepage_function =
1120                                        cond_instr(bl_samepage_trace);
1121                            } else {
1122                                    ic->f = cond_instr(bl);
1123                                    samepage_function = cond_instr(bl_samepage);
1124                            }
1125                  }                  }
1126    
1127                  ic->arg[0] = (iword & 0x00ffffff) << 2;                  ic->arg[0] = (iword & 0x00ffffff) << 2;
1128                  /*  Sign-extend:  */                  /*  Sign-extend:  */
1129                  if (ic->arg[0] & 0x02000000)                  if (ic->arg[0] & 0x02000000)
1130                          ic->arg[0] |= 0xfc000000;                          ic->arg[0] |= 0xfc000000;
1131                  /*  Branches are calculated as PC + 8 + offset:  */                  /*
1132                     *  Branches are calculated as PC + 8 + offset.
1133                     */
1134                  ic->arg[0] = (int32_t)(ic->arg[0] + 8);                  ic->arg[0] = (int32_t)(ic->arg[0] + 8);
1135    
1136                  /*  Special case: branch within the same page:  */                  /*  Special case: branch within the same page:  */
1137                  {                  {
1138                          uint32_t mask_within_page =                          uint32_t mask_within_page =
1139                              ((IC_ENTRIES_PER_PAGE-1) << 2) | 3;                              ((ARM_IC_ENTRIES_PER_PAGE-1) << 2) | 3;
1140                          uint32_t old_pc = addr;                          uint32_t old_pc = addr;
1141                          uint32_t new_pc = old_pc + (int32_t)ic->arg[0];                          uint32_t new_pc = old_pc + (int32_t)ic->arg[0];
1142                          if ((old_pc & ~mask_within_page) ==                          if ((old_pc & ~mask_within_page) ==
# Line 939  void arm_translate_instruction(struct cp Line 1153  void arm_translate_instruction(struct cp
1153          }          }
1154    
1155    
1156          /*  #define DYNTRANS_TO_BE_TRANSLATED_TAIL
1157           *  If we end up here, then an instruction was translated. Now it is  #include "cpu_dyntrans.c"
1158           *  time to check for combinations of instructions that can be  #undef  DYNTRANS_TO_BE_TRANSLATED_TAIL
          *  converted into a single function call.  
          */  
   
         /*  Single-stepping doesn't work with combinations:  */  
         if (single_step || cpu->machine->instruction_trace)  
                 return;  
   
         arm_combine_instructions(cpu, ic);  
   
         return;  
   
   
 bad:    /*  
          *  Nothing was translated. (Unimplemented or illegal instruction.)  
          */  
         quiet_mode = 0;  
         fatal("arm_translate_instruction(): TODO: "  
             "unimplemented ARM instruction:\n");  
         arm_cpu_disassemble_instr(cpu, ib, 1, 0, 0);  
         cpu->running = 0;  
         cpu->dead = 1;  
         cpu->cd.arm.running_translated = 0;  
         *ic = nothing_call;  
1159  }  }
1160    

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

  ViewVC Help
Powered by ViewVC 1.1.26