blob: 3a3c860bd2ad705464b34c45c55d5231c9ef59dd [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Alexander Astapchuk
*/
#include "open/vm_method_access.h"
#include "compiler.h"
#include "trace.h"
#ifdef WIN32
#include <malloc.h>
#endif
#include <memory.h>
#include <assert.h>
#include <stdlib.h>
#include "enc_ia32.h"
/**
* @file
* @brief CodeGen routines implementations specific for IA-32 and Intel 64.
*/
namespace Jitrino {
namespace Jet {
/**
* Provides fine-tuned implementation for IDIV/IREM operations on IA32-compatible platforms,
* in replacement of common arithmetic helper (see arith_rt.h).
*/
bool CodeGen::gen_a_platf(JavaByteCodes op, jtype jt)
{
if (jt != i32) return false;
if (op != OPCODE_IDIV && op != OPCODE_IREM) {
return false;
}
//
// The method is supposed to be platform-depended, and may not have
// Encoder support - leaving as-is, without implementing general
// support in Encoder
//
vpark(eax.reg());
vpark(edx.reg());
rlock(eax);
rlock(edx);
Val& v1 = vstack(1, vis_imm(1));
Val& v2 = vstack(0, true);
alu(alu_cmp, v2.as_opnd(), Opnd(-1));
unsigned br_normal = br(ne, 0, 0);
alu(alu_cmp, v1.as_opnd(), Opnd(INT_MIN));
unsigned br_exit = NOTHING;
if (op == OPCODE_IREM) {
do_mov(edx, Opnd(0)); // prepare exit value for the corner case
br_exit = br(eq, 0, 0);
}
else {
do_mov(eax, v1);
br_exit = br(eq, 0, 0);
}
patch(br_normal, ip());
do_mov(eax, v1);
//
// The method is supposed to be platform-depended, and may not have
// Encoder support - leaving as-is, without implementing general
// support in Encoder
//
//CDQ
EncoderBase::Operands args0(RegName_EDX, RegName_EAX);
ip(EncoderBase::encode(ip(), Mnemonic_CDQ, args0));
//IDIV
EncoderBase::Operands args(RegName_EDX, RegName_EAX,
devirt(v2.reg(), i32));
ip(EncoderBase::encode(ip(), Mnemonic_IDIV, args));
patch(br_exit, ip());
vpop();
vpop();
vpush(op == OPCODE_IREM ? edx : eax);
runlock(eax);
runlock(edx);
return true;
}
}}; // ~namespace Jitrino::Jet