/* -*- Mode: C; c-file-style:"gnu"; indent-tabs-mode:nil -*-
   operand_stack.h --
   Created: Chris Toshok <toshok@hungry.com>, 10-Aug-1997
 */
/*
  This file is part of Japhar, the GNU Virtual Machine for Java Bytecodes.
  Japhar is a project of The Hungry Programmers, GNU, and OryxSoft.

  Copyright (C) 1997, 1998, 1999 The Hungry Programmers

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Library General Public
  License as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Library General Public License for more details.

  You should have received a copy of the GNU Library General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
#ifndef _op_stack_h
#define _op_stack_h

#include "runtimeint.h"

PR_BEGIN_EXTERN_C

#define OPSTACK_SIZE 16384 /* 16k operand stacks */

#define op_stack_push_int(s, v) \
PR_BEGIN_MACRO \
    *((s)->stack_top++) = (void*)(PRInt32)(v); \
PR_END_MACRO

#define op_stack_push_long(s, v) \
PR_BEGIN_MACRO \
    *((s)->stack_top++) = (void*)(PRInt32)(((PRInt64)(v) >> 32) & 0xffffffff); \
    *((s)->stack_top++) = (void*)(PRInt32)((PRInt64)(v) & 0xffffffff); \
PR_END_MACRO

#define op_stack_push_doubleword(s, high_word, low_word) \
PR_BEGIN_MACRO \
    *((s)->stack_top++) = (void*)(high_word); \
    *((s)->stack_top++) = (void*)(low_word); \
PR_END_MACRO

#define op_stack_push_float(s, v) \
PR_BEGIN_MACRO \
  InterpValue newvalue; \
  newvalue.f = (v); \
  *((s)->stack_top++) = (void*)newvalue.i; \
PR_END_MACRO

#define op_stack_push_double(s, v) \
PR_BEGIN_MACRO \
  PRInt32 stack_value; \
  InterpValue val; \
  val.d = (v); \
  stack_value = (PRInt32)((val.j >> 32) & 0xffffffff); \
  *((s)->stack_top++) = (void*)stack_value; \
  stack_value = (PRInt32)(val.j & 0xffffffff); \
  *((s)->stack_top++) = (void*)stack_value; \
PR_END_MACRO

#define op_stack_push_object(s, o) \
PR_BEGIN_MACRO \
  *(s->stack_top++) = (void*)o; \
PR_END_MACRO

#define op_stack_pop_int(s, type, v) \
PR_BEGIN_MACRO \
  (v) = (PRInt32)*(--(s)->stack_top); \
PR_END_MACRO

#define promote_to_jint(t, vi, vo) \
PR_BEGIN_MACRO \
  switch (t) \
    { \
    case JSIG_CHAR: \
      (vo) = (PRInt32)(vi).c; \
      break; \
    case JSIG_BYTE: \
      (vo) = (PRInt32)(vi).b; \
      break; \
    case JSIG_SHORT: \
      (vo) = (PRInt32)(vi).s; \
      break; \
    case JSIG_BOOLEAN: \
      (vo) = (PRInt32)(vi).b; \
      break; \
    case JSIG_INT: \
    default: \
      (vo) = (vi).i; \
      break; \
  } \
PR_END_MACRO

#define op_stack_pop_long(s, v) \
PR_BEGIN_MACRO \
    InterpValue val1, val2; \
 \
    val2.i = (PRInt32)*(--(s)->stack_top); \
    val1.i = (PRInt32)*(--(s)->stack_top); \
 \
    (v) = (PRInt64)(PRUint32) val1.i << 32; \
    (v) |= (PRInt64)(PRUint32) val2.i; \
PR_END_MACRO

#define op_stack_pop_doubleword(s, word1, word2) \
PR_BEGIN_MACRO \
    (word2) = (PRInt32)*(--(s)->stack_top); \
    (word1) = (PRInt32)*(--(s)->stack_top); \
PR_END_MACRO

#define op_stack_pop_float(s, v) \
PR_BEGIN_MACRO \
    v = *(float*)(--(s)->stack_top); \
PR_END_MACRO

#define op_stack_pop_double(s, v) \
PR_BEGIN_MACRO \
    InterpValue val; \
    InterpValue val1, val2; \
    val.j = 0; \
 \
    val2.i = (PRInt32)*(--(s)->stack_top); \
    val1.i = (PRInt32)*(--(s)->stack_top); \
 \
    val.j = (PRInt64)(PRUint32) val1.i << 32; \
    val.j |= (PRInt64)(PRUint32) val2.i; \
 \
    (v) = val.d; \
PR_END_MACRO

#define op_stack_pop_object(s, obj) \
PR_BEGIN_MACRO \
    obj = (japhar_object*)*(--(s)->stack_top); \
PR_END_MACRO

#define op_stack_push_any(s, any) \
PR_BEGIN_MACRO \
    *((s)->stack_top++) = (any); \
PR_END_MACRO

#define op_stack_push_value(s, sig_str, value) \
PR_BEGIN_MACRO \
    if ((sig_str) == JSIG_DOUBLE) \
      op_stack_push_double(s, (value).d); \
    else if ((sig_str) == JSIG_LONG) \
      op_stack_push_long(s, (value).j); \
    else if ((sig_str) == JSIG_INT \
             || (sig_str) == JSIG_CHAR \
             || (sig_str) == JSIG_BYTE \
             || (sig_str) == JSIG_SHORT \
             || (sig_str) == JSIG_BOOLEAN) \
      { \
        PRInt32 v; \
        promote_to_jint((sig_str), value, v); \
        op_stack_push_int(s, v); \
      } \
    else \
      *((s)->stack_top++) = (void*)(value).i; \
PR_END_MACRO

#define op_stack_pop_any(s, any) \
PR_BEGIN_MACRO \
    (any) = *(--(s)->stack_top); \
PR_END_MACRO

#define op_stack_pop_value(stack, sig_str, v) \
PR_BEGIN_MACRO \
    switch ((sig_str)) \
      { \
      case JSIG_DOUBLE: \
        op_stack_pop_double((stack), (v).d); \
        break; \
      case JSIG_LONG: \
        op_stack_pop_long((stack), (v).j); \
        break; \
      case JSIG_BOOLEAN: \
        op_stack_pop_int((stack), PRUint8, (v).z); \
        break; \
      case JSIG_BYTE: \
        op_stack_pop_int((stack), PRInt8, (v).b); \
        break; \
      case JSIG_CHAR: \
        op_stack_pop_int((stack), PRUint16, (v).c); \
        break; \
      case JSIG_SHORT: \
        op_stack_pop_int((stack), PRInt16, (v).s); \
        break; \
      default: \
        (v).i = (PRInt32)*(--(stack)->stack_top); \
        break; \
  } \
PR_END_MACRO

PR_END_EXTERN_C

#endif /* _op_stack_h */
