/[gxemul]/trunk/src/cpus/cpu_avr_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/cpus/cpu_avr_instr.c

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

revision 22 by dpavlin, Mon Oct 8 16:19:37 2007 UTC revision 24 by dpavlin, Mon Oct 8 16:19:56 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_avr_instr.c,v 1.6 2006/02/09 22:40:27 debug Exp $   *  $Id: cpu_avr_instr.c,v 1.15 2006/03/05 16:20:24 debug Exp $
29   *   *
30   *  Atmel AVR (8-bit) instructions.   *  Atmel AVR (8-bit) instructions.
31   *   *
# Line 40  Line 40 
40  /*****************************************************************************/  /*****************************************************************************/
41    
42    
43    void push_value(struct cpu *cpu, uint32_t value, int len)
44    {
45            unsigned char data[4];
46            data[0] = value; data[1] = value >> 8;
47            data[2] = value >> 16; data[3] = value >> 24;
48            cpu->memory_rw(cpu, cpu->mem, cpu->cd.avr.sp + AVR_SRAM_BASE,
49                data, len, MEM_WRITE, CACHE_DATA);
50            cpu->cd.avr.sp -= len;
51            cpu->cd.avr.sp &= cpu->cd.avr.sram_mask;
52    }
53    
54    
55    void pop_value(struct cpu *cpu, uint32_t *value, int len)
56    {
57            unsigned char data[4];
58            cpu->cd.avr.sp += len;
59            cpu->cd.avr.sp &= cpu->cd.avr.sram_mask;
60            cpu->memory_rw(cpu, cpu->mem, cpu->cd.avr.sp + AVR_SRAM_BASE,
61                data, len, MEM_READ, CACHE_DATA);
62            *value = data[0];
63            if (len > 1)
64                    (*value) += (data[1] << 8);
65            if (len > 2)
66                    (*value) += (data[2] << 16);
67            if (len > 3)
68                    (*value) += (data[3] << 24);
69    }
70    
71    
72    /*****************************************************************************/
73    
74    
75  /*  /*
76   *  nop:  Do nothing.   *  nop:  Do nothing.
77   */   */
# Line 49  X(nop) Line 81  X(nop)
81    
82    
83  /*  /*
84     *  breq:  Conditional relative jump.
85     *
86     *  arg[1]: relative offset
87     */
88    X(breq)
89    {
90            uint32_t low_pc;
91    
92            if (!(cpu->cd.avr.sreg & AVR_SREG_Z))
93                    return;
94    
95            cpu->cd.avr.extra_cycles ++;
96    
97            /*  Calculate new PC from the next instruction + arg[1]  */
98            low_pc = ((size_t)ic - (size_t)cpu->cd.avr.cur_ic_page) /
99                sizeof(struct avr_instr_call);
100            cpu->pc &= ~((AVR_IC_ENTRIES_PER_PAGE-1)
101                << AVR_INSTR_ALIGNMENT_SHIFT);
102            cpu->pc += (low_pc << AVR_INSTR_ALIGNMENT_SHIFT);
103            cpu->pc += (int32_t)ic->arg[1];
104    
105            /*  Find the new physical page and update the translation pointers:  */
106            avr_pc_to_pointers(cpu);
107    }
108    
109    
110    /*
111     *  breq_samepage:  Continional relative jump (to within the same page).
112     *
113     *  arg[1] = pointer to new avr_instr_call
114     */
115    X(breq_samepage)
116    {
117            if (!(cpu->cd.avr.sreg & AVR_SREG_Z))
118                    return;
119    
120            cpu->cd.avr.extra_cycles ++;
121            cpu->cd.avr.next_ic = (struct avr_instr_call *) ic->arg[1];
122    }
123    
124    
125    /*
126     *  brne:  Conditional relative jump.
127     *
128     *  arg[1]: relative offset
129     */
130    X(brne)
131    {
132            uint32_t low_pc;
133    
134            if (cpu->cd.avr.sreg & AVR_SREG_Z)
135                    return;
136    
137            cpu->cd.avr.extra_cycles ++;
138    
139            /*  Calculate new PC from the next instruction + arg[1]  */
140            low_pc = ((size_t)ic - (size_t)cpu->cd.avr.cur_ic_page) /
141                sizeof(struct avr_instr_call);
142            cpu->pc &= ~((AVR_IC_ENTRIES_PER_PAGE-1)
143                << AVR_INSTR_ALIGNMENT_SHIFT);
144            cpu->pc += (low_pc << AVR_INSTR_ALIGNMENT_SHIFT);
145            cpu->pc += (int32_t)ic->arg[1];
146    
147            /*  Find the new physical page and update the translation pointers:  */
148            avr_pc_to_pointers(cpu);
149    }
150    
151    
152    /*
153     *  brne_samepage:  Continional relative jump (to within the same page).
154     *
155     *  arg[1] = pointer to new avr_instr_call
156     */
157    X(brne_samepage)
158    {
159            if (cpu->cd.avr.sreg & AVR_SREG_Z)
160                    return;
161    
162            cpu->cd.avr.extra_cycles ++;
163            cpu->cd.avr.next_ic = (struct avr_instr_call *) ic->arg[1];
164    }
165    
166    
167    /*
168   *  clX:  Clear an sreg bit.   *  clX:  Clear an sreg bit.
169   */   */
170  X(clc) { cpu->cd.avr.sreg &= ~AVR_SREG_C; }  X(clc) { cpu->cd.avr.sreg &= ~AVR_SREG_C; }
# Line 64  X(cli) { cpu->cd.avr.sreg &= ~AVR_SREG_I Line 180  X(cli) { cpu->cd.avr.sreg &= ~AVR_SREG_I
180  /*  /*
181   *  ldi:  Load immediate.   *  ldi:  Load immediate.
182   *   *
183   *  arg[0]: ptr to register   *  arg[1]: ptr to register
184   *  arg[1]: byte value   *  arg[2]: byte value
185   */   */
186  X(ldi)  X(ldi)
187  {  {
188          *(uint8_t *)(ic->arg[0]) = ic->arg[1];          *(uint8_t *)(ic->arg[1]) = ic->arg[2];
189  }  }
190    
191    
192  /*  /*
193   *  mov:  Copy register.   *  ld_y:  Load byte pointed to by register Y into a register.
194     *
195     *  arg[1]: ptr to rd
196     */
197    X(ld_y)
198    {
199            cpu->memory_rw(cpu, cpu->mem, AVR_SRAM_BASE + cpu->cd.avr.r[28]
200                + 256*cpu->cd.avr.r[29], (uint8_t *)(ic->arg[1]), 1, MEM_READ,
201                CACHE_DATA);
202            cpu->cd.avr.extra_cycles ++;
203    }
204    
205    
206    /*
207     *  out:  Write a byte from a register to I/O space.
208     *  (out is the generic function, out_* are special cases.)
209     *
210     *  arg[1]: ptr to rr
211     *  arg[2]: I/O port nr
212     */
213    X(out)
214    {
215            cpu->memory_rw(cpu, cpu->mem, AVR_SRAM_BASE + ic->arg[2],
216                (uint8_t *)(ic->arg[1]), 1, MEM_WRITE, CACHE_DATA);
217    }
218    X(out_ddra)  { cpu->cd.avr.ddra = *(uint8_t *)(ic->arg[1]); }
219    X(out_ddrb)  { cpu->cd.avr.ddrb = *(uint8_t *)(ic->arg[1]); }
220    X(out_ddrc)  { cpu->cd.avr.ddrc = *(uint8_t *)(ic->arg[1]); }
221    X(out_ddrd)  { cpu->cd.avr.ddrd = *(uint8_t *)(ic->arg[1]); }
222    X(out_porta) { cpu->cd.avr.portd_write = *(uint8_t *)(ic->arg[1]); }
223    X(out_portb) { cpu->cd.avr.portd_write = *(uint8_t *)(ic->arg[1]); }
224    X(out_portc) { cpu->cd.avr.portd_write = *(uint8_t *)(ic->arg[1]); }
225    X(out_portd) { cpu->cd.avr.portd_write = *(uint8_t *)(ic->arg[1]); }
226    
227    
228    /*
229     *  adiw:  rd+1:rd += constant
230     *
231     *  arg[1]: ptr to rd
232     *  arg[2]: k
233     */
234    X(adiw)
235    {
236            uint32_t value = *(uint8_t *)(ic->arg[1]) +
237                (*(uint8_t *)(ic->arg[1] + 1) << 8);
238            value += ic->arg[2];
239    
240            cpu->cd.avr.sreg &= ~(AVR_SREG_S | AVR_SREG_V | AVR_SREG_N
241                | AVR_SREG_Z | AVR_SREG_C);
242    
243            /*  TODO: is this V bit calculated correctly?  */
244            if (value > 0xffff)
245                    cpu->cd.avr.sreg |= AVR_SREG_C | AVR_SREG_V;
246            if (value & 0x8000)
247                    cpu->cd.avr.sreg |= AVR_SREG_N;
248            if (value == 0)
249                    cpu->cd.avr.sreg |= AVR_SREG_Z;
250    
251            if ((cpu->cd.avr.sreg & AVR_SREG_N? 1 : 0) ^
252                (cpu->cd.avr.sreg & AVR_SREG_V? 1 : 0))
253                    cpu->cd.avr.sreg |= AVR_SREG_S;
254    
255            *(uint8_t *)(ic->arg[1]) = value;
256            *(uint8_t *)(ic->arg[1] + 1) = value >> 8;
257    
258            cpu->cd.avr.extra_cycles ++;
259    }
260    
261    
262    /*
263     *  and:  rd = rd & rr
264     *
265     *  arg[1]: ptr to rr
266     *  arg[2]: ptr to rd
267     */
268    X(and)
269    {
270            *(uint8_t *)(ic->arg[2]) &= *(uint8_t *)(ic->arg[1]);
271            cpu->cd.avr.sreg &= ~(AVR_SREG_S | AVR_SREG_V | AVR_SREG_N
272                | AVR_SREG_Z);
273            if (*(uint8_t *)(ic->arg[2]) == 0)
274                    cpu->cd.avr.sreg |= AVR_SREG_Z;
275            if (*(uint8_t *)(ic->arg[2]) & 0x80)
276                    cpu->cd.avr.sreg |= AVR_SREG_S | AVR_SREG_N;
277    }
278    
279    
280    /*
281     *  eor:  rd = rd ^ rr
282     *
283     *  arg[1]: ptr to rr
284     *  arg[2]: ptr to rd
285     */
286    X(eor)
287    {
288            *(uint8_t *)(ic->arg[2]) ^= *(uint8_t *)(ic->arg[1]);
289            cpu->cd.avr.sreg &= ~(AVR_SREG_S | AVR_SREG_V | AVR_SREG_N
290                | AVR_SREG_Z);
291            if (*(uint8_t *)(ic->arg[2]) == 0)
292                    cpu->cd.avr.sreg |= AVR_SREG_Z;
293            if (*(uint8_t *)(ic->arg[2]) & 0x80)
294                    cpu->cd.avr.sreg |= AVR_SREG_S | AVR_SREG_N;
295    }
296    
297    
298    /*
299     *  andi:  rd = rd & imm
300   *   *
  *  arg[0]: ptr to rr  
301   *  arg[1]: ptr to rd   *  arg[1]: ptr to rd
302     *  arg[2]: imm
303     */
304    X(andi)
305    {
306            uint8_t x = *(uint8_t *)(ic->arg[1]) & ic->arg[2];
307            cpu->cd.avr.sreg &= ~(AVR_SREG_S | AVR_SREG_V | AVR_SREG_N
308                | AVR_SREG_Z);
309            if (x == 0)
310                    cpu->cd.avr.sreg |= AVR_SREG_Z;
311            if (x & 0x80)
312                    cpu->cd.avr.sreg |= AVR_SREG_S | AVR_SREG_N;
313            *(uint8_t *)(ic->arg[1]) = x;
314    }
315    
316    
317    /*
318     *  cpi:  Compare rd with immediate
319     *
320     *  arg[1]: ptr to rd
321     *  arg[2]: imm
322     */
323    X(cpi)
324    {
325            uint8_t x = *(uint8_t *)(ic->arg[1]), k = ic->arg[2], z = x - k;
326            cpu->cd.avr.sreg &= ~(AVR_SREG_S | AVR_SREG_V | AVR_SREG_N
327                | AVR_SREG_Z | AVR_SREG_H | AVR_SREG_C);
328            if (z == 0)
329                    cpu->cd.avr.sreg |= AVR_SREG_Z;
330            if (z & 0x80)
331                    cpu->cd.avr.sreg |= AVR_SREG_N;
332            /*  TODO: h and v bits!  */
333            if (abs((int)k) > abs((int)x))
334                    cpu->cd.avr.sreg |= AVR_SREG_C;
335            if ((cpu->cd.avr.sreg & AVR_SREG_N? 1 : 0) ^
336                (cpu->cd.avr.sreg & AVR_SREG_V? 1 : 0))
337                    cpu->cd.avr.sreg |= AVR_SREG_S;
338    }
339    
340    
341    /*
342     *  mov:  Copy register.
343     *
344     *  arg[1]: ptr to rr
345     *  arg[2]: ptr to rd
346   */   */
347  X(mov)  X(mov)
348  {  {
349          *(uint8_t *)(ic->arg[1]) = *(uint8_t *)(ic->arg[0]);          *(uint8_t *)(ic->arg[2]) = *(uint8_t *)(ic->arg[1]);
350    }
351    
352    
353    /*
354     *  sts:  Store a register into memory.
355     *
356     *  arg[1]: pointer to the register
357     *  arg[2]: absolute address (16 bits)
358     */
359    X(sts)
360    {
361            uint8_t r = *(uint8_t *)(ic->arg[1]);
362            if (!cpu->memory_rw(cpu, cpu->mem, ic->arg[2] + AVR_SRAM_BASE,
363                &r, sizeof(uint8_t), MEM_WRITE, CACHE_DATA)) {
364                    fatal("sts: write failed: TODO\n");
365                    exit(1);
366            }
367            cpu->cd.avr.extra_cycles ++;
368    }
369    
370    
371    /*
372     *  st_y:       Store a register into memory at address Y.
373     *  st_y_plus:  Store a register into memory at address Y, and update Y.
374     *  st_minus_y: Same as above, but with pre-decrement instead of post-increment.
375     *
376     *  arg[1]: pointer to the register
377     */
378    X(st_y)
379    {
380            uint16_t y = (cpu->cd.avr.r[29] << 8) + cpu->cd.avr.r[28];
381            cpu->memory_rw(cpu, cpu->mem, AVR_SRAM_BASE + y,
382                (uint8_t *)ic->arg[1], sizeof(uint8_t), MEM_WRITE, CACHE_DATA);
383            cpu->cd.avr.extra_cycles ++;
384    }
385    X(st_y_plus)
386    {
387            uint16_t y = (cpu->cd.avr.r[29] << 8) + cpu->cd.avr.r[28];
388            cpu->memory_rw(cpu, cpu->mem, AVR_SRAM_BASE + y,
389                (uint8_t *)ic->arg[1], sizeof(uint8_t), MEM_WRITE, CACHE_DATA);
390            cpu->cd.avr.extra_cycles ++;
391            y ++;
392            cpu->cd.avr.r[29] = y >> 8;
393            cpu->cd.avr.r[28] = y;
394    }
395    X(st_minus_y)
396    {
397            uint16_t y = (cpu->cd.avr.r[29] << 8) + cpu->cd.avr.r[28];
398            y --;
399            cpu->cd.avr.r[29] = y >> 8;
400            cpu->cd.avr.r[28] = y;
401            cpu->memory_rw(cpu, cpu->mem, AVR_SRAM_BASE + y,
402                (uint8_t *)ic->arg[1], sizeof(uint8_t), MEM_WRITE, CACHE_DATA);
403            cpu->cd.avr.extra_cycles ++;
404    }
405    
406    
407    /*
408     *  cbi,sbi:  Clear/Set bit in I/O register.
409     *
410     *  arg[1]: I/O register number (0..31)
411     *  arg[2]: byte mask to and/or into the old value (1, 2, ..., 0x40, or 0x80)
412     */
413    X(cbi)
414    {
415            uint8_t r;
416            cpu->memory_rw(cpu, cpu->mem, ic->arg[1] + AVR_SRAM_BASE,
417                &r, sizeof(uint8_t), MEM_READ, CACHE_DATA);
418            r &= ic->arg[2];
419            cpu->memory_rw(cpu, cpu->mem, ic->arg[1] + AVR_SRAM_BASE,
420                &r, sizeof(uint8_t), MEM_WRITE, CACHE_DATA);
421            cpu->cd.avr.extra_cycles ++;
422    }
423    X(sbi)
424    {
425            uint8_t r;
426            cpu->memory_rw(cpu, cpu->mem, ic->arg[1] + AVR_SRAM_BASE,
427                &r, sizeof(uint8_t), MEM_READ, CACHE_DATA);
428            r |= ic->arg[2];
429            cpu->memory_rw(cpu, cpu->mem, ic->arg[1] + AVR_SRAM_BASE,
430                &r, sizeof(uint8_t), MEM_WRITE, CACHE_DATA);
431            cpu->cd.avr.extra_cycles ++;
432    }
433    
434    
435    /*
436     *  lpm: Load program memory at addess Z into r0.
437     */
438    X(lpm)
439    {
440            uint16_t z = (cpu->cd.avr.r[31] << 8) + cpu->cd.avr.r[30];
441            cpu->memory_rw(cpu, cpu->mem, z, &cpu->cd.avr.r[0],
442                sizeof(uint8_t), MEM_READ, CACHE_DATA);
443            cpu->cd.avr.extra_cycles += 2;
444    }
445    
446    
447    /*
448     *  ret:  Return from subroutine call.
449     */
450    X(ret)
451    {
452            uint32_t new_pc;
453    
454            cpu->cd.avr.extra_cycles += 3 + cpu->cd.avr.is_22bit;
455    
456            /*  Pop the address of the following instruction:  */
457            pop_value(cpu, &new_pc, 2 + cpu->cd.avr.is_22bit);
458            cpu->pc = new_pc << 1;
459    
460            /*  Find the new physical page and update the translation pointers:  */
461            avr_pc_to_pointers(cpu);
462    }
463    
464    
465    /*
466     *  rcall:  Relative call.
467     *
468     *  arg[1]: relative offset
469     */
470    X(rcall)
471    {
472            uint32_t low_pc;
473    
474            cpu->cd.avr.extra_cycles += 2 + cpu->cd.avr.is_22bit;
475    
476            /*  Push the address of the following instruction:  */
477            low_pc = ((size_t)ic - (size_t)cpu->cd.avr.cur_ic_page) /
478                sizeof(struct avr_instr_call);
479            cpu->pc &= ~((AVR_IC_ENTRIES_PER_PAGE-1)
480                << AVR_INSTR_ALIGNMENT_SHIFT);
481            cpu->pc += (low_pc << AVR_INSTR_ALIGNMENT_SHIFT);
482            push_value(cpu, (cpu->pc >> 1) + 1, 2 + cpu->cd.avr.is_22bit);
483    
484            /*  Calculate new PC from the next instruction + arg[1]  */
485            cpu->pc += (int32_t)ic->arg[1];
486    
487            /*  Find the new physical page and update the translation pointers:  */
488            avr_pc_to_pointers(cpu);
489  }  }
490    
491    
492  /*  /*
493   *  rjmp:  Relative jump.   *  rjmp:  Relative jump.
494   *   *
495   *  arg[0]: relative offset   *  arg[1]: relative offset
496   */   */
497  X(rjmp)  X(rjmp)
498  {  {
# Line 96  X(rjmp) Line 500  X(rjmp)
500    
501          cpu->cd.avr.extra_cycles ++;          cpu->cd.avr.extra_cycles ++;
502    
503          /*  Calculate new PC from the next instruction + arg[0]  */          /*  Calculate new PC from the next instruction + arg[1]  */
504          low_pc = ((size_t)ic - (size_t)cpu->cd.avr.cur_ic_page) /          low_pc = ((size_t)ic - (size_t)cpu->cd.avr.cur_ic_page) /
505              sizeof(struct avr_instr_call);              sizeof(struct avr_instr_call);
506          cpu->pc &= ~((AVR_IC_ENTRIES_PER_PAGE-1)          cpu->pc &= ~((AVR_IC_ENTRIES_PER_PAGE-1)
507              << AVR_INSTR_ALIGNMENT_SHIFT);              << AVR_INSTR_ALIGNMENT_SHIFT);
508          cpu->pc += (low_pc << AVR_INSTR_ALIGNMENT_SHIFT);          cpu->pc += (low_pc << AVR_INSTR_ALIGNMENT_SHIFT);
509          cpu->pc += (int32_t)ic->arg[0];          cpu->pc += (int32_t)ic->arg[1];
510    
511          /*  Find the new physical page and update the translation pointers:  */          /*  Find the new physical page and update the translation pointers:  */
512          avr_pc_to_pointers(cpu);          avr_pc_to_pointers(cpu);
# Line 112  X(rjmp) Line 516  X(rjmp)
516  /*  /*
517   *  rjmp_samepage:  Relative jump (to within the same translated page).   *  rjmp_samepage:  Relative jump (to within the same translated page).
518   *   *
519   *  arg[0] = pointer to new avr_instr_call   *  arg[1] = pointer to new avr_instr_call
520   */   */
521  X(rjmp_samepage)  X(rjmp_samepage)
522  {  {
523          cpu->cd.avr.extra_cycles ++;          cpu->cd.avr.extra_cycles ++;
524          cpu->cd.avr.next_ic = (struct avr_instr_call *) ic->arg[0];          cpu->cd.avr.next_ic = (struct avr_instr_call *) ic->arg[1];
525  }  }
526    
527    
# Line 135  X(sei) { cpu->cd.avr.sreg |= AVR_SREG_I; Line 539  X(sei) { cpu->cd.avr.sreg |= AVR_SREG_I;
539    
540    
541  /*  /*
542   *  swap:  Swap nibbles.   *  push, pop:  Push/pop a register onto/from the stack.
543   *   *
544   *  arg[0]: ptr to rd   *  arg[1]: ptr to rd
545     */
546    X(push) { push_value(cpu, *(uint8_t *)(ic->arg[1]), 1);
547              cpu->cd.avr.extra_cycles ++; }
548    X(pop)  { uint32_t t; pop_value(cpu, &t, 1); *(uint8_t *)(ic->arg[1]) = t;
549              cpu->cd.avr.extra_cycles ++; }
550    
551    
552    /*
553     *  inc, dec:  Increment/decrement a register.
554     *
555     *  arg[1]: ptr to rd
556     */
557    X(inc)
558    {
559            uint8_t x = *(uint8_t *)(ic->arg[1]) + 1;
560            cpu->cd.avr.sreg &= ~(AVR_SREG_S | AVR_SREG_V | AVR_SREG_N
561                | AVR_SREG_Z);
562            if (x == 0)
563                    cpu->cd.avr.sreg |= AVR_SREG_Z;
564            if (x == 0x80)
565                    cpu->cd.avr.sreg |= AVR_SREG_V;
566            if (x & 0x80)
567                    cpu->cd.avr.sreg |= AVR_SREG_N;
568            if ((cpu->cd.avr.sreg & AVR_SREG_N? 1 : 0) ^
569                (cpu->cd.avr.sreg & AVR_SREG_V? 1 : 0))
570                    cpu->cd.avr.sreg |= AVR_SREG_S;
571            *(uint8_t *)(ic->arg[1]) = x;
572    }
573    X(dec)
574    {
575            uint8_t x = *(uint8_t *)(ic->arg[1]) - 1;
576            cpu->cd.avr.sreg &= ~(AVR_SREG_S | AVR_SREG_V | AVR_SREG_N
577                | AVR_SREG_Z);
578            if (x == 0)
579                    cpu->cd.avr.sreg |= AVR_SREG_Z;
580            if (x == 0x7f)
581                    cpu->cd.avr.sreg |= AVR_SREG_V;
582            if (x & 0x80)
583                    cpu->cd.avr.sreg |= AVR_SREG_N;
584            if ((cpu->cd.avr.sreg & AVR_SREG_N? 1 : 0) ^
585                (cpu->cd.avr.sreg & AVR_SREG_V? 1 : 0))
586                    cpu->cd.avr.sreg |= AVR_SREG_S;
587            *(uint8_t *)(ic->arg[1]) = x;
588    }
589    
590    
591    /*
592     *  swap:  Swap nibbles in a register.
593     *
594     *  arg[1]: ptr to rd
595   */   */
596  X(swap)  X(swap)
597  {  {
598          uint8_t x = *(uint8_t *)(ic->arg[0]);          uint8_t x = *(uint8_t *)(ic->arg[1]);
599          *(uint8_t *)(ic->arg[0]) = (x >> 4) | (x << 4);          *(uint8_t *)(ic->arg[1]) = (x >> 4) | (x << 4);
600  }  }
601    
602    
# Line 188  void avr_combine_instructions(struct cpu Line 642  void avr_combine_instructions(struct cpu
642  /*****************************************************************************/  /*****************************************************************************/
643    
644    
645    static uint16_t read_word(struct cpu *cpu, unsigned char *ib, int addr)
646    {
647            uint16_t iword;
648            unsigned char *page = cpu->cd.avr.host_load[addr >> 12];
649    
650            if (page != NULL) {
651                    /*  fatal("TRANSLATION HIT!\n");  */
652                    memcpy(ib, page + (addr & 0xfff), sizeof(uint16_t));
653            } else {
654                    /*  fatal("TRANSLATION MISS!\n");  */
655                    if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
656                        sizeof(uint16_t), MEM_READ, CACHE_INSTRUCTION)) {
657                            fatal("to_be_translated(): "
658                                "read failed: TODO\n");
659                            exit(1);
660                    }
661            }
662    
663            iword = *((uint16_t *)&ib[0]);
664    
665    #ifdef HOST_BIG_ENDIAN
666            iword = ((iword & 0xff) << 8) |
667                    ((iword & 0xff00) >> 8);
668    #endif
669            return iword;
670    }
671    
672    
673  /*  /*
674   *  avr_instr_to_be_translated():   *  avr_instr_to_be_translated():
675   *   *
# Line 198  void avr_combine_instructions(struct cpu Line 680  void avr_combine_instructions(struct cpu
680   */   */
681  X(to_be_translated)  X(to_be_translated)
682  {  {
683          int addr, low_pc, rd, rr, main_opcode;          int addr, low_pc, rd, rr, tmp, main_opcode, a;
 #ifdef DYNTRANS_BACKEND  
         int simple = 0;  
 #endif  
684          uint16_t iword;          uint16_t iword;
         unsigned char *page;  
685          unsigned char ib[2];          unsigned char ib[2];
686          void (*samepage_function)(struct cpu *, struct avr_instr_call *);          void (*samepage_function)(struct cpu *, struct avr_instr_call *);
687    
# Line 219  X(to_be_translated) Line 697  X(to_be_translated)
697          addr &= cpu->cd.avr.pc_mask;          addr &= cpu->cd.avr.pc_mask;
698    
699          /*  Read the instruction word from memory:  */          /*  Read the instruction word from memory:  */
700          page = cpu->cd.avr.host_load[addr >> 12];          iword = read_word(cpu, ib, addr);
   
         if (page != NULL) {  
                 /*  fatal("TRANSLATION HIT!\n");  */  
                 memcpy(ib, page + (addr & 0xfff), sizeof(ib));  
         } else {  
                 /*  fatal("TRANSLATION MISS!\n");  */  
                 if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,  
                     sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {  
                         fatal("to_be_translated(): "  
                             "read failed: TODO\n");  
                         goto bad;  
                 }  
         }  
   
         iword = *((uint16_t *)&ib[0]);  
   
 #ifdef HOST_BIG_ENDIAN  
         iword = ((iword & 0xff) << 8) |  
                 ((iword & 0xff00) >> 8);  
 #endif  
701    
702    
703  #define DYNTRANS_TO_BE_TRANSLATED_HEAD  #define DYNTRANS_TO_BE_TRANSLATED_HEAD
# Line 247  X(to_be_translated) Line 705  X(to_be_translated)
705  #undef  DYNTRANS_TO_BE_TRANSLATED_HEAD  #undef  DYNTRANS_TO_BE_TRANSLATED_HEAD
706    
707    
708            /*  Default instruction length:  */
709            ic->arg[0] = 1;
710    
711    
712          /*          /*
713           *  Translate the instruction:           *  Translate the instruction:
714           */           */
# Line 262  X(to_be_translated) Line 724  X(to_be_translated)
724                  goto bad;                  goto bad;
725    
726          case 0x2:          case 0x2:
727                    if ((iword & 0xfc00) == 0x2000) {
728                            rd = (iword & 0x1f0) >> 4;
729                            rr = ((iword & 0x200) >> 5) | (iword & 0xf);
730                            ic->f = instr(and);
731                            ic->arg[1] = (size_t)(&cpu->cd.avr.r[rr]);
732                            ic->arg[2] = (size_t)(&cpu->cd.avr.r[rd]);
733                            break;
734                    }
735                    if ((iword & 0xfc00) == 0x2400) {
736                            rd = (iword & 0x1f0) >> 4;
737                            rr = ((iword & 0x200) >> 5) | (iword & 0xf);
738                            ic->f = instr(eor);
739                            ic->arg[1] = (size_t)(&cpu->cd.avr.r[rr]);
740                            ic->arg[2] = (size_t)(&cpu->cd.avr.r[rd]);
741                            break;
742                    }
743                  if ((iword & 0xfc00) == 0x2c00) {                  if ((iword & 0xfc00) == 0x2c00) {
744                          rd = (iword & 0x1f0) >> 4;                          rd = (iword & 0x1f0) >> 4;
745                          rr = ((iword & 0x200) >> 5) | (iword & 0xf);                          rr = ((iword & 0x200) >> 5) | (iword & 0xf);
746                          ic->f = instr(mov);                          ic->f = instr(mov);
747                          ic->arg[0] = (size_t)(&cpu->cd.avr.r[rr]);                          ic->arg[1] = (size_t)(&cpu->cd.avr.r[rr]);
748                            ic->arg[2] = (size_t)(&cpu->cd.avr.r[rd]);
749                            break;
750                    }
751                    goto bad;
752    
753            case 0x3:
754                    rd = ((iword >> 4) & 15) + 16;
755                    ic->f = instr(cpi);
756                    ic->arg[1] = (size_t)(&cpu->cd.avr.r[rd]);
757                    ic->arg[2] = ((iword >> 4) & 0xf0) + (iword & 0xf);
758                    break;
759    
760            case 0x7:
761                    rd = ((iword >> 4) & 15) + 16;
762                    ic->f = instr(andi);
763                    ic->arg[1] = (size_t)(&cpu->cd.avr.r[rd]);
764                    ic->arg[2] = ((iword >> 4) & 0xf0) + (iword & 0xf);
765                    break;
766    
767            case 0x8:
768                    if ((iword & 0xfe0f) == 0x8008) {
769                            rd = (iword >> 4) & 31;
770                            ic->f = instr(ld_y);
771                            ic->arg[1] = (size_t)(&cpu->cd.avr.r[rd]);
772                            break;
773                    }
774                    if ((iword & 0xfe0f) == 0x8208) {
775                            rd = (iword >> 4) & 31;
776                            ic->f = instr(st_y);
777                          ic->arg[1] = (size_t)(&cpu->cd.avr.r[rd]);                          ic->arg[1] = (size_t)(&cpu->cd.avr.r[rd]);
778                          break;                          break;
779                  }                  }
780                  goto bad;                  goto bad;
781    
782          case 0x9:          case 0x9:
783                    if ((iword & 0xfe0f) == 0x900f) {
784                            rd = (iword >> 4) & 31;
785                            ic->f = instr(pop);
786                            ic->arg[1] = (size_t)(&cpu->cd.avr.r[rd]);
787                            break;
788                    }
789                    if ((iword & 0xfe0f) == 0x9200) {
790                            uint8_t tmpbytes[2];
791                            ic->arg[0] = 2; /*  Note: 2 words!  */
792                            ic->f = instr(sts);
793                            rd = (iword >> 4) & 31;
794                            ic->arg[1] = (size_t)(&cpu->cd.avr.r[rd]);
795                            ic->arg[2] = read_word(cpu, tmpbytes, addr + 2);
796                            break;
797                    }
798                    if ((iword & 0xfe0f) == 0x9209) {
799                            rd = (iword >> 4) & 31;
800                            ic->f = instr(st_y_plus);
801                            ic->arg[1] = (size_t)(&cpu->cd.avr.r[rd]);
802                            break;
803                    }
804                    if ((iword & 0xfe0f) == 0x920a) {
805                            rd = (iword >> 4) & 31;
806                            ic->f = instr(st_minus_y);
807                            ic->arg[1] = (size_t)(&cpu->cd.avr.r[rd]);
808                            break;
809                    }
810                    if ((iword & 0xfe0f) == 0x920f) {
811                            rd = (iword >> 4) & 31;
812                            ic->f = instr(push);
813                            ic->arg[1] = (size_t)(&cpu->cd.avr.r[rd]);
814                            break;
815                    }
816                  if ((iword & 0xfe0f) == 0x9402) {                  if ((iword & 0xfe0f) == 0x9402) {
817                          rd = (iword >> 4) & 31;                          rd = (iword >> 4) & 31;
818                          ic->f = instr(swap);                          ic->f = instr(swap);
819                          ic->arg[0] = (size_t)(&cpu->cd.avr.r[rd]);                          ic->arg[1] = (size_t)(&cpu->cd.avr.r[rd]);
820                            break;
821                    }
822                    if ((iword & 0xfe0f) == 0x9403) {
823                            rd = (iword >> 4) & 31;
824                            ic->f = instr(inc);
825                            ic->arg[1] = (size_t)(&cpu->cd.avr.r[rd]);
826                          break;                          break;
827                  }                  }
828                  if ((iword & 0xff8f) == 0x9408) {                  if ((iword & 0xff8f) == 0x9408) {
# Line 292  X(to_be_translated) Line 838  X(to_be_translated)
838                          }                          }
839                          break;                          break;
840                  }                  }
841                    if ((iword & 0xfe0f) == 0x940a) {
842                            rd = (iword >> 4) & 31;
843                            ic->f = instr(dec);
844                            ic->arg[1] = (size_t)(&cpu->cd.avr.r[rd]);
845                            break;
846                    }
847                  if ((iword & 0xff8f) == 0x9488) {                  if ((iword & 0xff8f) == 0x9488) {
848                          switch ((iword >> 4) & 7) {                          switch ((iword >> 4) & 7) {
849                          case 0: ic->f = instr(clc); break;                          case 0: ic->f = instr(clc); break;
# Line 305  X(to_be_translated) Line 857  X(to_be_translated)
857                          }                          }
858                          break;                          break;
859                  }                  }
860                    if ((iword & 0xffff) == 0x9508) {
861                            ic->f = instr(ret);
862                            break;
863                    }
864                    if ((iword & 0xffff) == 0x95c8) {
865                            ic->f = instr(lpm);
866                            break;
867                    }
868                    if ((iword & 0xff00) == 0x9600) {
869                            ic->f = instr(adiw);
870                            rd = ((iword >> 3) & 6) + 24;
871                            ic->arg[1] = (size_t)(&cpu->cd.avr.r[rd]);
872                            ic->arg[2] = (iword & 15) + ((iword & 0xc0) >> 2);
873                            break;
874                    }
875                    if ((iword & 0xfd00) == 0x9800) {
876                            if (iword & 0x200)
877                                    ic->f = instr(sbi);
878                            else
879                                    ic->f = instr(cbi);
880                            ic->arg[1] = (iword >> 3) & 31;
881                            ic->arg[2] = 1 << (iword & 7);
882                            if (!(iword & 0x200))
883                                    ic->arg[2] = ~ic->arg[2];
884                            break;
885                    }
886                    goto bad;
887    
888            case 0xb:
889                    if ((iword & 0xf800) == 0xb800) {
890                            a = ((iword & 0x600) >> 5) | (iword & 0xf);
891                            rr = (iword >> 4) & 31;
892                            ic->arg[1] = (size_t)(&cpu->cd.avr.r[rr]);
893                            ic->arg[2] = a;
894                            switch (a) {
895                            case 0x1a: ic->f = instr(out_ddra); break;
896                            case 0x17: ic->f = instr(out_ddrb); break;
897                            case 0x14: ic->f = instr(out_ddrc); break;
898                            case 0x11: ic->f = instr(out_ddrd); break;
899                            case 0x1b: ic->f = instr(out_porta); break;
900                            case 0x18: ic->f = instr(out_portb); break;
901                            case 0x15: ic->f = instr(out_portc); break;
902                            case 0x12: ic->f = instr(out_portd); break;
903                            default:ic->f = instr(out);
904                            }
905                            break;
906                    }
907                  goto bad;                  goto bad;
908    
909          case 0xc:          case 0xc:       /*  rjmp  */
910                  ic->f = instr(rjmp);          case 0xd:       /*  rcall  */
911                  samepage_function = instr(rjmp_samepage);                  samepage_function = NULL;
912                  ic->arg[0] = (((int16_t)((iword & 0x0fff) << 4)) >> 3) + 2;                  switch (main_opcode) {
913                    case 0xc:
914                            ic->f = instr(rjmp);
915                            samepage_function = instr(rjmp_samepage);
916                            break;
917                    case 0xd:
918                            ic->f = instr(rcall);
919                            break;
920                    }
921                    ic->arg[1] = (((int16_t)((iword & 0x0fff) << 4)) >> 3) + 2;
922                  /*  Special case: branch within the same page:  */                  /*  Special case: branch within the same page:  */
923                  {                  if (samepage_function != NULL) {
924                          uint32_t mask_within_page =                          uint32_t mask_within_page =
925                              ((AVR_IC_ENTRIES_PER_PAGE-1) <<                              ((AVR_IC_ENTRIES_PER_PAGE-1) <<
926                              AVR_INSTR_ALIGNMENT_SHIFT) |                              AVR_INSTR_ALIGNMENT_SHIFT) |
927                              ((1 << AVR_INSTR_ALIGNMENT_SHIFT) - 1);                              ((1 << AVR_INSTR_ALIGNMENT_SHIFT) - 1);
928                          uint32_t old_pc = addr;                          uint32_t old_pc = addr;
929                          uint32_t new_pc = old_pc + (int32_t)ic->arg[0];                          uint32_t new_pc = old_pc + (int32_t)ic->arg[1];
930                          if ((old_pc & ~mask_within_page) ==                          if ((old_pc & ~mask_within_page) ==
931                              (new_pc & ~mask_within_page)) {                              (new_pc & ~mask_within_page)) {
932                                  ic->f = samepage_function;                                  ic->f = samepage_function;
933                                  ic->arg[0] = (size_t) (                                  ic->arg[1] = (size_t) (
934                                      cpu->cd.avr.cur_ic_page +                                      cpu->cd.avr.cur_ic_page +
935                                      ((new_pc & mask_within_page) >>                                      ((new_pc & mask_within_page) >>
936                                      AVR_INSTR_ALIGNMENT_SHIFT));                                      AVR_INSTR_ALIGNMENT_SHIFT));
# Line 333  X(to_be_translated) Line 941  X(to_be_translated)
941          case 0xe:          case 0xe:
942                  rd = ((iword >> 4) & 0xf) + 16;                  rd = ((iword >> 4) & 0xf) + 16;
943                  ic->f = instr(ldi);                  ic->f = instr(ldi);
944                  ic->arg[0] = (size_t)(&cpu->cd.avr.r[rd]);                  ic->arg[1] = (size_t)(&cpu->cd.avr.r[rd]);
945                  ic->arg[1] = ((iword >> 4) & 0xf0) | (iword & 0xf);                  ic->arg[2] = ((iword >> 4) & 0xf0) | (iword & 0xf);
946                  break;                  break;
947    
948            case 0xf:
949                    if ((iword & 0xfc07) == 0xf001) {
950                            ic->f = instr(breq);
951                            samepage_function = instr(breq_samepage);
952                            tmp = (iword >> 3) & 0x7f;
953                            if (tmp >= 64)
954                                    tmp -= 128;
955                            ic->arg[1] = (tmp + 1) * 2;
956                            /*  Special case: branch within the same page:  */
957                            if (samepage_function != NULL) {
958                                    uint32_t mask_within_page =
959                                        ((AVR_IC_ENTRIES_PER_PAGE-1) <<
960                                        AVR_INSTR_ALIGNMENT_SHIFT) |
961                                        ((1 << AVR_INSTR_ALIGNMENT_SHIFT) - 1);
962                                    uint32_t old_pc = addr;
963                                    uint32_t new_pc = old_pc + (int32_t)ic->arg[1];
964                                    if ((old_pc & ~mask_within_page) ==
965                                        (new_pc & ~mask_within_page)) {
966                                            ic->f = samepage_function;
967                                            ic->arg[1] = (size_t) (
968                                                cpu->cd.avr.cur_ic_page +
969                                                ((new_pc & mask_within_page) >>
970                                                AVR_INSTR_ALIGNMENT_SHIFT));
971                                    }
972                            }
973                            break;
974                    }
975    /*  TODO: refactor  */
976                    if ((iword & 0xfc07) == 0xf401) {
977                            ic->f = instr(brne);
978                            samepage_function = instr(brne_samepage);
979                            tmp = (iword >> 3) & 0x7f;
980                            if (tmp >= 64)
981                                    tmp -= 128;
982                            ic->arg[1] = (tmp + 1) * 2;
983                            /*  Special case: branch within the same page:  */
984                            if (samepage_function != NULL) {
985                                    uint32_t mask_within_page =
986                                        ((AVR_IC_ENTRIES_PER_PAGE-1) <<
987                                        AVR_INSTR_ALIGNMENT_SHIFT) |
988                                        ((1 << AVR_INSTR_ALIGNMENT_SHIFT) - 1);
989                                    uint32_t old_pc = addr;
990                                    uint32_t new_pc = old_pc + (int32_t)ic->arg[1];
991                                    if ((old_pc & ~mask_within_page) ==
992                                        (new_pc & ~mask_within_page)) {
993                                            ic->f = samepage_function;
994                                            ic->arg[1] = (size_t) (
995                                                cpu->cd.avr.cur_ic_page +
996                                                ((new_pc & mask_within_page) >>
997                                                AVR_INSTR_ALIGNMENT_SHIFT));
998                                    }
999                            }
1000                            break;
1001                    }
1002                    goto bad;
1003    
1004          default:goto bad;          default:goto bad;
1005          }          }
1006    

Legend:
Removed from v.22  
changed lines
  Added in v.24

  ViewVC Help
Powered by ViewVC 1.1.26