Main Page | File List | Globals | Related Pages

stack.c

Go to the documentation of this file.
00001 /* 00002 * $Id: stack.c,v 1.13 2003/12/01 09:10:16 troth Exp $ 00003 * 00004 **************************************************************************** 00005 * 00006 * simulavr - A simulator for the Atmel AVR family of microcontrollers. 00007 * Copyright (C) 2001, 2002, 2003 Theodore A. Roth 00008 * 00009 * This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software 00021 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00022 * 00023 **************************************************************************** 00024 */ 00025 00026 /** \file stack.c 00027 \brief Module for the definition of the stack. 00028 00029 Defines the classes stack, hw_stack, and mem_stack. 00030 00031 FIXME: Ted, I would really really really love to put in a description of 00032 what is the difference between these three classes and how they're used, 00033 but I don't understand it myself. */ 00034 00035 #include <config.h> 00036 00037 #include <stdio.h> 00038 #include <stdlib.h> 00039 00040 #include "avrerror.h" 00041 #include "avrmalloc.h" 00042 #include "avrclass.h" 00043 #include "utils.h" 00044 #include "callback.h" 00045 #include "op_names.h" 00046 00047 #include "storage.h" 00048 #include "flash.h" 00049 00050 #include "vdevs.h" 00051 #include "memory.h" 00052 #include "stack.h" 00053 #include "register.h" 00054 #include "sram.h" 00055 #include "eeprom.h" 00056 #include "timers.h" 00057 #include "ports.h" 00058 00059 #include "avrcore.h" 00060 00061 #include "display.h" 00062 00063 static uint32_t hw_pop (Stack *stack, int bytes); 00064 static void hw_push (Stack *stack, int bytes, uint32_t val); 00065 00066 static uint32_t mem_pop (Stack *stack, int bytes); 00067 static void mem_push (Stack *stack, int bytes, uint32_t val); 00068 00069 /****************************************************************************\ 00070 * 00071 * Stack(AvrClass) Definition. 00072 * 00073 \****************************************************************************/ 00074 00075 /** \brief Allocates memory for a new Stack object 00076 00077 This is a virtual method for higher level stack implementations and as 00078 such should not be used directly. */ 00079 00080 Stack * 00081 stack_new (StackFP_Pop pop, StackFP_Push push) 00082 { 00083 Stack *st; 00084 00085 st = avr_new (Stack, 1); 00086 stack_construct (st, pop, push); 00087 class_overload_destroy ((AvrClass *)st, stack_destroy); 00088 00089 return st; 00090 } 00091 00092 /** \brief Constructor for the Stack class. 00093 00094 This is a virtual method for higher level stack implementations and as 00095 such should not be used directly. */ 00096 00097 void 00098 stack_construct (Stack *stack, StackFP_Pop pop, StackFP_Push push) 00099 { 00100 if (stack == NULL) 00101 avr_error ("passed null ptr"); 00102 00103 class_construct ((AvrClass *)stack); 00104 00105 stack->pop = pop; 00106 stack->push = push; 00107 } 00108 00109 /** \brief Destructor for the Stack class. 00110 00111 This is a virtual method for higher level stack implementations and as 00112 such should not be used directly. */ 00113 00114 void 00115 stack_destroy (void *stack) 00116 { 00117 if (stack == NULL) 00118 return; 00119 00120 class_destroy (stack); 00121 } 00122 00123 /** \brief Pops a byte or a word off the stack and returns it. 00124 \param stack A pointer to the Stack object from which to pop 00125 \param bytes Number of bytes to pop off the stack (1 to 4 bytes). 00126 00127 \return The 1 to 4 bytes value popped from the stack. 00128 00129 This method provides access to the derived class's pop() method. */ 00130 00131 uint32_t 00132 stack_pop (Stack *stack, int bytes) 00133 { 00134 return stack->pop (stack, bytes); 00135 } 00136 00137 /** \brief Pushes a byte or a word of data onto the stack. 00138 \param stack A pointer to the Stack object from which to pop. 00139 \param bytes Size of the value being pushed onto the stack (1 to 4 bytes). 00140 \param val The value to be pushed. 00141 00142 This method provides access to the derived class's push() method. */ 00143 00144 void 00145 stack_push (Stack *stack, int bytes, uint32_t val) 00146 { 00147 stack->push (stack, bytes, val); 00148 } 00149 00150 /****************************************************************************\ 00151 * 00152 * HWStack(Stack) Definition. 00153 * 00154 \****************************************************************************/ 00155 00156 /** \brief Allocate a new HWStack object 00157 00158 This is the stack implementation used by devices which lack SRAM and only 00159 have a fixed size hardware stack (e.i., the at90s1200) */ 00160 00161 HWStack * 00162 hwstack_new (int depth) 00163 { 00164 HWStack *st; 00165 00166 st = avr_new (HWStack, 1); 00167 hwstack_construct (st, depth); 00168 class_overload_destroy ((AvrClass *)st, hwstack_destroy); 00169 00170 return st; 00171 } 00172 00173 /** \brief Constructor for HWStack object */ 00174 00175 void 00176 hwstack_construct (HWStack *stack, int depth) 00177 { 00178 if (stack == NULL) 00179 avr_error ("passed null ptr"); 00180 00181 stack_construct ((Stack *)stack, hw_pop, hw_push); 00182 00183 stack->depth = depth; 00184 stack->stack = avr_new0 (uint32_t, depth); 00185 } 00186 00187 /** \brief Destructor for HWStack object */ 00188 00189 void 00190 hwstack_destroy (void *stack) 00191 { 00192 if (stack == NULL) 00193 return; 00194 00195 avr_free (((HWStack *)stack)->stack); 00196 stack_destroy (stack); 00197 } 00198 00199 /* The HWStack pop method. */ 00200 00201 static uint32_t 00202 hw_pop (Stack *stack, int bytes) 00203 { 00204 HWStack *hwst = (HWStack *)stack; 00205 int i; 00206 uint32_t val = hwst->stack[0]; 00207 00208 for (i = 0; i < (hwst->depth - 1); i++) 00209 { 00210 hwst->stack[i] = hwst->stack[i + 1]; 00211 } 00212 00213 return val; 00214 } 00215 00216 /* The HWStack push method. */ 00217 00218 static void 00219 hw_push (Stack *stack, int bytes, uint32_t val) 00220 { 00221 HWStack *hwst = (HWStack *)stack; 00222 int i; 00223 00224 for (i = (hwst->depth - 1); i; i--) 00225 { 00226 hwst->stack[i - 1] = hwst->stack[i]; 00227 } 00228 00229 hwst->stack[0] = val; 00230 } 00231 00232 /****************************************************************************\ 00233 * 00234 * StackPointer(VDevice) Definition. 00235 * 00236 \****************************************************************************/ 00237 00238 #ifndef DOXYGEN /* don't expose to doxygen */ 00239 00240 typedef struct _StackPointer StackPointer; 00241 struct _StackPointer 00242 { 00243 VDevice parent; 00244 uint8_t SPL; /* Low byte of stack pointer */ 00245 uint8_t SPH; /* High byte of stack pointer */ 00246 }; 00247 00248 #endif 00249 00250 static void sp_construct (StackPointer *sp); 00251 static void sp_destroy (void *sp); 00252 static uint8_t sp_read (VDevice *dev, int addr); 00253 static void sp_write (VDevice *dev, int addr, uint8_t val); 00254 static void sp_reset (VDevice *dev); 00255 static uint16_t sp_get (VDevice *sp); 00256 static void sp_set (VDevice *sp, uint16_t val); 00257 static char *sp_name (VDevice *dev, int addr); 00258 00259 static StackPointer * 00260 sp_new (void) 00261 { 00262 StackPointer *sp; 00263 00264 sp = avr_new (StackPointer, 1); 00265 sp_construct (sp); 00266 class_overload_destroy ((AvrClass *)sp, sp_destroy); 00267 00268 return sp; 00269 } 00270 00271 static void 00272 sp_construct (StackPointer *sp) 00273 { 00274 char *name = "StackPointer"; 00275 00276 if (sp == NULL) 00277 avr_error ("passed null ptr"); 00278 00279 vdev_construct ((VDevice *)sp, name, STACK_POINTER_BASE, 00280 STACK_POINTER_SIZE, sp_read, sp_write, sp_reset, sp_name); 00281 00282 sp_reset ((VDevice *)sp); 00283 } 00284 00285 static void 00286 sp_destroy (void *sp) 00287 { 00288 if (sp == NULL) 00289 return; 00290 00291 vdev_destroy (sp); 00292 } 00293 00294 static uint8_t 00295 sp_read (VDevice *dev, int addr) 00296 { 00297 StackPointer *sp = (StackPointer *)dev; 00298 00299 if (0 == (addr - vdev_get_base (dev))) 00300 return sp->SPL; 00301 else 00302 return sp->SPH; 00303 } 00304 00305 static void 00306 sp_write (VDevice *dev, int addr, uint8_t val) 00307 { 00308 /* Don't need display_io_reg() here since it's called higher up in mem 00309 chain. */ 00310 00311 StackPointer *sp = (StackPointer *)dev; 00312 00313 if (0 == (addr - vdev_get_base (dev))) 00314 sp->SPL = val; 00315 else 00316 sp->SPH = val; 00317 } 00318 00319 static void 00320 sp_reset (VDevice *dev) 00321 { 00322 StackPointer *sp = (StackPointer *)dev; 00323 00324 display_io_reg (SPL_IO_REG, sp->SPL = 0); 00325 display_io_reg (SPH_IO_REG, sp->SPH = 0); 00326 } 00327 00328 static uint16_t 00329 sp_get (VDevice *sp) 00330 { 00331 return (((StackPointer *)sp)->SPH << 8) + ((StackPointer *)sp)->SPL; 00332 } 00333 00334 static void 00335 sp_set (VDevice *sp, uint16_t val) 00336 { 00337 display_io_reg (SPL_IO_REG, ((StackPointer *)sp)->SPL = val & 0xff); 00338 display_io_reg (SPH_IO_REG, ((StackPointer *)sp)->SPH = val >> 8); 00339 } 00340 00341 static char * 00342 sp_name (VDevice *dev, int addr) 00343 { 00344 switch (addr) 00345 { 00346 case 0x5d: 00347 return "SPL"; 00348 case 0x5e: 00349 return "SPH"; 00350 } 00351 return NULL; 00352 } 00353 00354 /****************************************************************************\ 00355 * 00356 * MemStack(Stack) Definition. 00357 * 00358 \****************************************************************************/ 00359 00360 /** \brief Allocate a new MemStack object */ 00361 00362 MemStack * 00363 memstack_new (Memory *mem) 00364 { 00365 MemStack *st; 00366 00367 st = avr_new (MemStack, 1); 00368 memstack_construct (st, mem); 00369 class_overload_destroy ((AvrClass *)st, memstack_destroy); 00370 00371 return st; 00372 } 00373 00374 /** \brief Constructor for MemStack object */ 00375 00376 void 00377 memstack_construct (MemStack *stack, Memory *mem) 00378 { 00379 if (stack == NULL) 00380 avr_error ("passed null ptr"); 00381 00382 stack_construct ((Stack *)stack, mem_pop, mem_push); 00383 00384 class_ref ((AvrClass *)mem); 00385 stack->mem = mem; 00386 00387 /* FIXME: Is this a circular reference? */ 00388 stack->SP = (VDevice *)sp_new (); 00389 mem_attach (stack->mem, stack->SP); 00390 } 00391 00392 /** \brief Destructor for MemStack object */ 00393 00394 void 00395 memstack_destroy (void *stack) 00396 { 00397 MemStack *_stack = (MemStack *)stack; 00398 00399 if (stack == NULL) 00400 return; 00401 00402 class_unref ((AvrClass *)_stack->SP); 00403 class_unref ((AvrClass *)_stack->mem); 00404 00405 stack_destroy (stack); 00406 } 00407 00408 /* The MemStack pop method */ 00409 00410 static uint32_t 00411 mem_pop (Stack *stack, int bytes) 00412 { 00413 MemStack *mst = (MemStack *)stack; 00414 int i; 00415 uint32_t val = 0; 00416 uint16_t sp = sp_get (mst->SP); 00417 00418 if ((bytes < 0) || (bytes >= sizeof (uint32_t))) 00419 avr_error ("bytes out of bounds: %d", bytes); 00420 00421 for (i = bytes - 1; i >= 0; i--) 00422 { 00423 sp++; 00424 val |= (mem_read (mst->mem, sp) << (i * 8)); 00425 } 00426 00427 sp_set (mst->SP, sp); 00428 00429 return val; 00430 } 00431 00432 /* The MemStack push method. */ 00433 00434 static void 00435 mem_push (Stack *stack, int bytes, uint32_t val) 00436 { 00437 MemStack *mst = (MemStack *)stack; 00438 int i; 00439 uint16_t sp = sp_get (mst->SP); 00440 00441 if ((bytes < 0) || (bytes >= sizeof (uint32_t))) 00442 avr_error ("bytes out of bounds: %d", bytes); 00443 00444 for (i = 0; i < bytes; i++) 00445 { 00446 mem_write (mst->mem, sp, val & 0xff); 00447 val >>= 8; 00448 sp--; 00449 } 00450 00451 sp_set (mst->SP, sp); 00452 }

Automatically generated by Doxygen 1.3.8 on 11 Aug 2004.