stack.c
Go to the documentation of this file.
1 /*
2  * $Id: stack.c,v 1.15 2004/01/30 07:09:56 troth Exp $
3  *
4  ****************************************************************************
5  *
6  * simulavr - A simulator for the Atmel AVR family of microcontrollers.
7  * Copyright (C) 2001, 2002, 2003, 2004 Theodore A. Roth
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  *
23  ****************************************************************************
24  */
25 
26 /** \file stack.c
27  \brief Module for the definition of the stack.
28 
29  Defines the classes stack, hw_stack, and mem_stack.
30 
31  FIXME: Ted, I would really really really love to put in a description of
32  what is the difference between these three classes and how they're used,
33  but I don't understand it myself. */
34 
35 #include <config.h>
36 
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 
41 #include "avrerror.h"
42 #include "avrmalloc.h"
43 #include "avrclass.h"
44 #include "utils.h"
45 #include "callback.h"
46 #include "op_names.h"
47 
48 #include "storage.h"
49 #include "flash.h"
50 
51 #include "vdevs.h"
52 #include "memory.h"
53 #include "stack.h"
54 #include "register.h"
55 #include "sram.h"
56 #include "eeprom.h"
57 #include "timers.h"
58 #include "ports.h"
59 
60 #include "avrcore.h"
61 
62 #include "display.h"
63 
64 static uint32_t hw_pop (Stack *stack, int bytes);
65 static void hw_push (Stack *stack, int bytes, uint32_t val);
66 
67 static uint32_t mem_pop (Stack *stack, int bytes);
68 static void mem_push (Stack *stack, int bytes, uint32_t val);
69 
70 /****************************************************************************\
71  *
72  * Stack(AvrClass) Definition.
73  *
74 \****************************************************************************/
75 
76 /** \brief Allocates memory for a new Stack object
77 
78  This is a virtual method for higher level stack implementations and as
79  such should not be used directly. */
80 
81 Stack *
82 stack_new (StackFP_Pop pop, StackFP_Push push)
83 {
84  Stack *st;
85 
86  st = avr_new (Stack, 1);
87  stack_construct (st, pop, push);
88  class_overload_destroy ((AvrClass *)st, stack_destroy);
89 
90  return st;
91 }
92 
93 /** \brief Constructor for the Stack class.
94 
95  This is a virtual method for higher level stack implementations and as
96  such should not be used directly. */
97 
98 void
99 stack_construct (Stack *stack, StackFP_Pop pop, StackFP_Push push)
100 {
101  if (stack == NULL)
102  avr_error ("passed null ptr");
103 
104  class_construct ((AvrClass *)stack);
105 
106  stack->pop = pop;
107  stack->push = push;
108 }
109 
110 /** \brief Destructor for the Stack class.
111 
112  This is a virtual method for higher level stack implementations and as
113  such should not be used directly. */
114 
115 void
116 stack_destroy (void *stack)
117 {
118  if (stack == NULL)
119  return;
120 
121  class_destroy (stack);
122 }
123 
124 /** \brief Pops a byte or a word off the stack and returns it.
125  \param stack A pointer to the Stack object from which to pop
126  \param bytes Number of bytes to pop off the stack (1 to 4 bytes).
127 
128  \return The 1 to 4 bytes value popped from the stack.
129 
130  This method provides access to the derived class's pop() method. */
131 
132 uint32_t
133 stack_pop (Stack *stack, int bytes)
134 {
135  return stack->pop (stack, bytes);
136 }
137 
138 /** \brief Pushes a byte or a word of data onto the stack.
139  \param stack A pointer to the Stack object from which to pop.
140  \param bytes Size of the value being pushed onto the stack (1 to 4 bytes).
141  \param val The value to be pushed.
142 
143  This method provides access to the derived class's push() method. */
144 
145 void
146 stack_push (Stack *stack, int bytes, uint32_t val)
147 {
148  stack->push (stack, bytes, val);
149 }
150 
151 /****************************************************************************\
152  *
153  * HWStack(Stack) Definition.
154  *
155 \****************************************************************************/
156 
157 /** \brief Allocate a new HWStack object
158 
159  This is the stack implementation used by devices which lack SRAM and only
160  have a fixed size hardware stack (e.i., the at90s1200) */
161 
162 HWStack *
163 hwstack_new (int depth)
164 {
165  HWStack *st;
166 
167  st = avr_new (HWStack, 1);
168  hwstack_construct (st, depth);
169  class_overload_destroy ((AvrClass *)st, hwstack_destroy);
170 
171  return st;
172 }
173 
174 /** \brief Constructor for HWStack object */
175 
176 void
177 hwstack_construct (HWStack *stack, int depth)
178 {
179  if (stack == NULL)
180  avr_error ("passed null ptr");
181 
182  stack_construct ((Stack *)stack, hw_pop, hw_push);
183 
184  stack->depth = depth;
185  stack->stack = avr_new0 (uint32_t, depth);
186 }
187 
188 /** \brief Destructor for HWStack object */
189 
190 void
191 hwstack_destroy (void *stack)
192 {
193  if (stack == NULL)
194  return;
195 
196  avr_free (((HWStack *)stack)->stack);
197  stack_destroy (stack);
198 }
199 
200 /* The HWStack pop method. */
201 
202 static uint32_t
203 hw_pop (Stack *stack, int bytes)
204 {
205  HWStack *hwst = (HWStack *)stack;
206  int i;
207  uint32_t val = hwst->stack[0];
208 
209  for (i = 0; i < (hwst->depth - 1); i++)
210  {
211  hwst->stack[i] = hwst->stack[i + 1];
212  }
213 
214  return val;
215 }
216 
217 /* The HWStack push method. */
218 
219 static void
220 hw_push (Stack *stack, int bytes, uint32_t val)
221 {
222  HWStack *hwst = (HWStack *)stack;
223  int i;
224 
225  for (i = (hwst->depth - 1); i; i--)
226  {
227  hwst->stack[i - 1] = hwst->stack[i];
228  }
229 
230  hwst->stack[0] = val;
231 }
232 
233 /****************************************************************************\
234  *
235  * StackPointer(VDevice) Definition.
236  *
237 \****************************************************************************/
238 
239 #ifndef DOXYGEN /* don't expose to doxygen */
240 
241 typedef struct _StackPointer StackPointer;
242 struct _StackPointer
243 {
244  VDevice parent;
245 
246  uint16_t SPL_addr; /* Since some devices don't have a SPH, we
247  only track SPL address and assume the SPH
248  address is SPL_addr + 1. */
249 
250  uint8_t SPL; /* Low byte of stack pointer */
251  uint8_t SPH; /* High byte of stack pointer */
252 };
253 
254 #endif
255 
256 static StackPointer *sp_new (int addr, char *name);
257 static void sp_construct (StackPointer *sp, int addr, char *name);
258 static void sp_destroy (void *sp);
259 static uint8_t sp_read (VDevice *dev, int addr);
260 static void sp_write (VDevice *dev, int addr, uint8_t val);
261 static void sp_reset (VDevice *dev);
262 static uint16_t sp_get (VDevice *sp);
263 static void sp_set (VDevice *sp, uint16_t val);
264 static void sp_add_addr (VDevice *vdev, int addr, char *name, int rel_addr,
265  void *data);
266 
267 /** \brief Create the Stack Pointer VDevice.
268 
269  This should only be used in the DevSuppDefn io reg init structure. */
270 
271 VDevice *
272 sp_create (int addr, char *name, int rel_addr, void *data)
273 {
274  return (VDevice *)sp_new (addr, name);
275 }
276 
277 static StackPointer *
278 sp_new (int addr, char *name)
279 {
280  StackPointer *sp;
281 
282  sp = avr_new (StackPointer, 1);
283  sp_construct (sp, addr, name);
284  class_overload_destroy ((AvrClass *)sp, sp_destroy);
285 
286  return sp;
287 }
288 
289 static void
290 sp_construct (StackPointer *sp, int addr, char *name)
291 {
292  if (sp == NULL)
293  avr_error ("passed null ptr");
294 
295  vdev_construct ((VDevice *)sp, sp_read, sp_write, sp_reset, sp_add_addr);
296 
297  sp_add_addr ((VDevice *)sp, addr, name, 0, NULL);
298 
299  sp_reset ((VDevice *)sp);
300 }
301 
302 static void
303 sp_destroy (void *sp)
304 {
305  if (sp == NULL)
306  return;
307 
308  vdev_destroy (sp);
309 }
310 
311 static uint8_t
312 sp_read (VDevice *dev, int addr)
313 {
314  StackPointer *sp = (StackPointer *)dev;
315 
316  if (addr == sp->SPL_addr)
317  return sp->SPL;
318  else if (addr == (sp->SPL_addr + 1))
319  return sp->SPH;
320  else
321  avr_error ("Bad address: 0x%04x", addr);
322 
323  return 0;
324 }
325 
326 static void
327 sp_write (VDevice *dev, int addr, uint8_t val)
328 {
329  /* Don't need display_io_reg() here since it's called higher up in mem
330  chain. */
331 
332  StackPointer *sp = (StackPointer *)dev;
333 
334  if (addr == sp->SPL_addr)
335  sp->SPL = val;
336  else if (addr == (sp->SPL_addr + 1))
337  sp->SPH = val;
338  else
339  avr_error ("Bad address: 0x%04x", addr);
340 }
341 
342 static void
343 sp_reset (VDevice *dev)
344 {
345  StackPointer *sp = (StackPointer *)dev;
346 
347  display_io_reg (SPL_IO_REG, sp->SPL = 0);
348  display_io_reg (SPH_IO_REG, sp->SPH = 0);
349 }
350 
351 static uint16_t
352 sp_get (VDevice *sp)
353 {
354  return (((StackPointer *)sp)->SPH << 8) + ((StackPointer *)sp)->SPL;
355 }
356 
357 static void
358 sp_set (VDevice *sp, uint16_t val)
359 {
360  display_io_reg (SPL_IO_REG, ((StackPointer *)sp)->SPL = val & 0xff);
361  display_io_reg (SPH_IO_REG, ((StackPointer *)sp)->SPH = val >> 8);
362 }
363 
364 static void
365 sp_add_addr (VDevice *vdev, int addr, char *name, int rel_addr, void *data)
366 {
367  StackPointer *sp = (StackPointer *)vdev;
368 
369  if (strncmp ("SPL", name, 3) == 0)
370  sp->SPL_addr = addr;
371 
372  else if (strncmp ("SPH", name, 3) == 0)
373  ;
374 
375  else
376  avr_error ("Bad address: 0x%04x", addr);
377 }
378 
379 /****************************************************************************\
380  *
381  * MemStack(Stack) Definition.
382  *
383 \****************************************************************************/
384 
385 /** \brief Allocate a new MemStack object */
386 
387 MemStack *
388 memstack_new (Memory *mem, int spl_addr)
389 {
390  MemStack *st;
391 
392  st = avr_new (MemStack, 1);
393  memstack_construct (st, mem, spl_addr);
394  class_overload_destroy ((AvrClass *)st, memstack_destroy);
395 
396  return st;
397 }
398 
399 /** \brief Constructor for MemStack object */
400 
401 void
402 memstack_construct (MemStack *stack, Memory *mem, int spl_addr)
403 {
404  if (stack == NULL)
405  avr_error ("passed null ptr");
406 
407  stack_construct ((Stack *)stack, mem_pop, mem_push);
408 
409  class_ref ((AvrClass *)mem);
410  stack->mem = mem;
411 
412  stack->SP = mem_get_vdevice_by_addr (mem, spl_addr);
413  if (stack->SP == NULL)
414  {
415  avr_error ("attempt to attach non-extistant SPL register");
416  }
417  class_ref ((AvrClass *)stack->SP);
418 }
419 
420 /** \brief Destructor for MemStack object */
421 
422 void
423 memstack_destroy (void *stack)
424 {
425  MemStack *_stack = (MemStack *)stack;
426 
427  if (stack == NULL)
428  return;
429 
430  class_unref ((AvrClass *)_stack->SP);
431  class_unref ((AvrClass *)_stack->mem);
432 
433  stack_destroy (stack);
434 }
435 
436 /* The MemStack pop method */
437 
438 static uint32_t
439 mem_pop (Stack *stack, int bytes)
440 {
441  MemStack *mst = (MemStack *)stack;
442  int i;
443  uint32_t val = 0;
444  uint16_t sp = sp_get (mst->SP);
445 
446  if ((bytes < 0) || (bytes >= sizeof (uint32_t)))
447  avr_error ("bytes out of bounds: %d", bytes);
448 
449  for (i = bytes - 1; i >= 0; i--)
450  {
451  sp++;
452  val |= (mem_read (mst->mem, sp) << (i * 8));
453  }
454 
455  sp_set (mst->SP, sp);
456 
457  return val;
458 }
459 
460 /* The MemStack push method. */
461 
462 static void
463 mem_push (Stack *stack, int bytes, uint32_t val)
464 {
465  MemStack *mst = (MemStack *)stack;
466  int i;
467  uint16_t sp = sp_get (mst->SP);
468 
469  if ((bytes < 0) || (bytes >= sizeof (uint32_t)))
470  avr_error ("bytes out of bounds: %d", bytes);
471 
472  for (i = 0; i < bytes; i++)
473  {
474  mem_write (mst->mem, sp, val & 0xff);
475  val >>= 8;
476  sp--;
477  }
478 
479  sp_set (mst->SP, sp);
480 }

Automatically generated by Doxygen 1.8.2 on Mon Aug 18 2014.