/*
 * Copyright (C) 2018-2020 Western Digital Corporation or its affiliates
 * Copyright (C) 2017-2018 Wearable, Inc.
 * Copyright (C) 2000-2012 leJOS Contributors
 * Copyright (C) 2000 Jose H. Solorzano and TinyVM Contributors
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 * 
 * This Source Code Form is “Incompatible With Secondary Licenses”,
 * as defined by the Mozilla Public License, v. 2.0.
 */

/**
 * This is included inside a switch statement.
 */

OPCODE(OP_BIPUSH)
  // Stack size: +1
  // Arguments: 1
  // TBD: check negatives
  push_word ((JBYTE) (*pc++));
  DISPATCH;

OPCODE(OP_SIPUSH)
  // Stack size: +1
  // Arguments: 2
  push_word ((JSHORT) (((uint16_t) pc[0] << 8) | pc[1]));
  pc += 2;
  DISPATCH;

OPCODE(OP_LDC)
  // Stack size: +1
  // Arguments: 1
  // Optimized version for ints/floats only.
  push_word(*(((STACKWORD *)get_constant_values_base(pState)) + pc[0]));
  pc++;
  DISPATCH;

OPCODE(OP_LDC_1)
OPCODE(OP_LDC_2)
MULTI_OPCODE(OP_LDC_3)
MULTI_OPCODE(OP_LDC_4)
MULTI_OPCODE(OP_LDC_5)
MULTI_OPCODE(OP_LDC_6)
MULTI_OPCODE(OP_LDC_7)
MULTI_OPCODE(OP_LDC_8)
MULTI_OPCODE(OP_LDC_9)
MULTI_OPCODE(OP_LDC_10)
MULTI_OPCODE(OP_LDC_11)
MULTI_OPCODE(OP_LDC_12)
MULTI_OPCODE(OP_LDC_13)
MULTI_OPCODE(OP_LDC_14)
MULTI_OPCODE(OP_LDC_15)
MULTI_OPCODE(OP_LDC_16)
  {
    ConstantRecord* tempConstRec = get_constant_record (pState, (*(pc-1) - OP_LDC_1)*256 + *pc);
    // Stack size: +1
    // Arguments: 1
    switch (tempConstRec->constantType)
    {
      case JAVA_LANG_STRING:
      case AC:
        // Optimized and none optimized strings
        {
          SAVE_REGS(pState);
          Object* tempWordPtr = new_string (pState, tempConstRec);
          LOAD_REGS(pState);
          if (tempWordPtr == NULL) {
            DISPATCH_CHECKED;
          }
          push_ref(obj2ref(tempWordPtr));
        }
        break;
      case T_CLASS:
        push_ref(ptr2ref(get_class_record(pState, *get_constant_ptr(pState, tempConstRec))));
        break;
      case T_INT:
      case T_FLOAT:
        push_word(*(STACKWORD *)get_constant_ptr(pState, tempConstRec));
        break;
      #ifdef VERIFY
      default:
        assert (false, INTERPRETER0);
      #endif
    }
    pc++;
  }
  DISPATCH;

OPCODE(OP_LDC2_W)
  // Stack size: +2
  // Arguments: 2
  {
    ConstantRecord* tempConstRec = get_constant_record (pState, ((uint16_t) pc[0] << 8) | pc[1]);
    STACKWORD* tempWordPtr = (STACKWORD *)get_constant_ptr (pState, tempConstRec);
    push_word(*tempWordPtr++);
    push_word(*tempWordPtr);
    pc += 2;
  }
  DISPATCH;

OPCODE(OP_ACONST_NULL)
  // Stack size: +1
  // Arguments: 0
  push_ref(ptr2ref(NULL));
  DISPATCH;

OPCODE(OP_ICONST_M1)
  push_word (-1);
  DISPATCH;

OPCODE(OP_ICONST_0)
  push_word (0);
  DISPATCH;

OPCODE(OP_ICONST_1)
  push_word (1);
  DISPATCH;

OPCODE(OP_ICONST_2)
  push_word (2);
  DISPATCH;

OPCODE(OP_ICONST_3)
  push_word (3);
  DISPATCH;

OPCODE(OP_ICONST_4)
  push_word (4);
  DISPATCH;

OPCODE(OP_ICONST_5)
  push_word (5);
  DISPATCH;

OPCODE(OP_LCONST_0)
OPCODE(OP_LCONST_1)
  // Stack size: +2
  // Arguments: 0
  push_word (0);
  push_word (*(pc-1) - OP_LCONST_0);
  DISPATCH;

OPCODE(OP_DCONST_0)
  push_word (0);
  // Fall through!
OPCODE(OP_FCONST_0)
  push_word (0);
  DISPATCH;  

OPCODE(OP_POP2)
  // Stack size: -2
  // Arguments: 0
  just_pop_word();
  // Fall through
OPCODE(OP_POP)
  // Stack size: -1
  // Arguments: 0
  just_pop_word();
  DISPATCH;

OPCODE(OP_DUP)
  // Stack size: +1
  // Arguments: 0
  dup();
  DISPATCH;

OPCODE(OP_DUP2)
  // Stack size: +2
  // Arguments: 0
  dup2();
  DISPATCH;

OPCODE(OP_DUP_X1)
  // Stack size: +1
  // Arguments: 0
  dup_x1();
  DISPATCH;

OPCODE(OP_DUP2_X1)
  // Stack size: +2
  // Arguments: 0
  dup2_x1();
  DISPATCH;

OPCODE(OP_DUP_X2)
  // Stack size: +1
  // Arguments: 0
  dup_x2();
  DISPATCH;

OPCODE(OP_DUP2_X2)
  // Stack size: +2
  // Arguments: 0
  dup2_x2();
  DISPATCH;



OPCODE(OP_SWAP)
  swap(); 
  DISPATCH;


#if FP_ARITHMETIC
  
OPCODE(OP_FCONST_1)
  push_word (jfloat2word((JFLOAT) 1.0));
  DISPATCH;

OPCODE(OP_FCONST_2)
  push_word (jfloat2word((JFLOAT) 2.0));
  DISPATCH;

#endif // FP_ARITHMETIC

#if FP_DOUBLE_ARITHMETIC

OPCODE(OP_DCONST_1)
  // Stack size: +2
  // Arguments: 0
  {
    JDOUBLE d1;
    d1 = 1.0;
    push_jdouble(&d1);
  }
  DISPATCH;

#endif
  
// Notes)
// - LDC_W should not occur in TinyVM or CompactVM.
// - Arguments of LDC and LDC2_W are postprocessed.
// - NOP is in op_skip.hc.

/*end*/







