next up previous contents
Next: 7. System limits Up: 6. Miscellaneous data structures Previous: 6.4.1 Freezing strings into

6.5 Miscellaneous x86 dependent utilities

\subsection{Machine dependent stacks}

To isolate the system from stack details (growing direction, etc.) we use machine dependent stack objects. No matter the machine convention, it can be assumed that a stack grows from high to low addresses if this class is used.

<Off machine dependent stack. >= (U->)
// A machine dependent stack.
//
class off_mdepStck {
protected:
  vm_offset_t s_sp;               // stack pointer.
  <Other protected methods of off_mdepStck. >
public:
  // Creates an mdep  stack which pretends to grow downwards. 
  off_mdepStck(const vm_offset_t sp) : s_sp(sp) {}

  <Other public methods of off_mdepStck. >
};

Defines off_mdepStck (links are to index).

A stack (which is an stack pointer) can be converted to a pointer to machine words.

<Other public methods of off_mdepStck. >= (<-U) [D->]
operator vm_offset_t*(void){ 
  assert(sizeof(vm_offset_t)==sizeof(vm_offset_t*));
  return (vm_offset_t*)s_sp; 
}
operator natural_t(void){ 
  assert(sizeof(natural_t)==sizeof(vm_offset_t));
  return (natural_t)s_sp; 
}

<Off machine dependent stack dependencies. >= (U->)
#include <flux/types.h>         // for vm_offset_t et al.
#include <assert.h>             // for assert

On Intels, the stack grows to the left (to low addresses). This method can be used to check the stack direction.

<Other public methods of off_mdepStck. >+= (<-U) [<-D->]
inline static boolean_t grows_to_right(void); 

<off_mdepStck::grows_to_right implementation. >= (U->)
// On intels stack grow right to left (hi to lo).
inline boolean_t off_mdepStck::grows_to_right(void) { return FALSE; }

The common operators are provided to do pointer arithmetic.

<Other public methods of off_mdepStck. >+= (<-U) [<-D->]
// Common stack operators. 
off_mdepStck operator+(vm_size_t s) const  
 { return off_mdepStck(s_sp+s); }
off_mdepStck operator-(vm_size_t s) const
 { return off_mdepStck(s_sp-s); }
off_mdepStck &operator++(void) 
 { s_sp++; return *this; }
off_mdepStck &operator--(void) 
 { s_sp--; return *this; }
off_mdepStck &operator+=(const vm_size_t s) 
 { s_sp+=s; return *this; }
off_mdepStck &operator-=(const vm_size_t s) 
 { s_sp-=s; return *this; }
boolean_t operator<(const off_mdepStck a_stck) const
 {  return s_sp < a_stck.s_sp; }
boolean_t operator>(const off_mdepStck a_stck) const
 {  return s_sp > a_stck.s_sp; }
boolean_t operator<=(const off_mdepStck a_stck) const
 {  return s_sp <= a_stck.s_sp; }
boolean_t operator>=(const off_mdepStck a_stck) const
 {  return s_sp >= a_stck.s_sp; }

Usual stack operations are provided too.

<Other public methods of off_mdepStck. >+= (<-U) [<-D->]
off_mdepStck &pushb(const unsigned8_t i) 
  {*(vm_offset_t*)--s_sp=(vm_offset_t)i; return *this;}
off_mdepStck &pushs(const unsigned16_t i) 
  {*(vm_offset_t*)--s_sp=(vm_offset_t)i; return *this;}
off_mdepStck &push(const unsigned32_t i) 
  {*(vm_offset_t*)--s_sp=(vm_offset_t)i; return *this;}
off_mdepStck &pushd(const unsigned64_t i) 
{push(hi(i)); push(lo(i)); return *this;}
off_mdepStck &popb(unsigned8_t &i) 
  {i=(unsigned8_t)*(vm_offset_t*)s_sp; s_sp++; return *this;}
off_mdepStck &pops(unsigned16_t &i) 
  {i=(unsigned16_t)*(vm_offset_t*)s_sp; s_sp++; return *this;}
off_mdepStck &pop(unsigned32_t &i) 
  {i=(unsigned32_t)*(vm_offset_t*)s_sp; s_sp++; return *this;}
off_mdepStck &popd(unsigned64_t &i) 
  {i=*(unsigned64_t *)s_sp; s_sp+=2; return *this;}

Where

<Other protected methods of off_mdepStck. >= (<-U)
unsigned32_t hi(unsigned64_t i){ return ((unsigned32_t)(i>>32)); }
unsigned32_t lo(unsigned64_t i){ return ((unsigned32_t)(i&0xffffffff)); }

This other method allocates a region to push multiple words in the stack and return the starting address of the pushed words.

<Other public methods of off_mdepStck. >+= (<-U) [<-D]
void *alloca(vm_size_t nbytes) {
  s_sp -= nbytes;
  return (void*)s_sp;
}

\subsubsection{Machine dependent stacks \cpp{} source files}

Stack code is kept in klib/mdep/mStck.h.

<mdep mStck.h*>=
<Read the literate code instead warning. >
#ifndef __OFF_MDEP_STCK_H
#define __OFF_MDEP_STCK_H 1

<Off machine dependent stack dependencies. >

<Off machine dependent stack. >

<off_mdepStck::grows_to_right implementation. >

#endif // __OFF_MDEP_STCK_H

%% --------------------------------------------------------------


Francisco J. Ballesteros
1998-05-25