12 #ifndef V8_S390_SIMULATOR_S390_H_ 13 #define V8_S390_SIMULATOR_S390_H_ 15 #include "src/allocation.h" 17 #if defined(USE_SIMULATOR) 20 #include "src/assembler.h" 21 #include "src/base/hashmap.h" 22 #include "src/s390/constants-s390.h" 23 #include "src/simulator-base.h" 30 static const int LINE_VALID = 0;
31 static const int LINE_INVALID = 1;
33 static const int kPageShift = 12;
34 static const int kPageSize = 1 << kPageShift;
35 static const int kPageMask = kPageSize - 1;
36 static const int kLineShift = 2;
37 static const int kLineLength = 1 << kLineShift;
38 static const int kLineMask = kLineLength - 1;
40 CachePage() { memset(&validity_map_, LINE_INVALID,
sizeof(validity_map_)); }
42 char* ValidityByte(
int offset) {
43 return &validity_map_[offset >> kLineShift];
46 char* CachedData(
int offset) {
return &data_[offset]; }
49 char data_[kPageSize];
50 static const int kValidityMapSize = kPageSize >> kLineShift;
51 char validity_map_[kValidityMapSize];
54 class Simulator :
public SimulatorBase {
56 friend class S390Debugger;
100 explicit Simulator(Isolate* isolate);
108 void set_register(
int reg, uint64_t value);
109 uint64_t get_register(
int reg)
const;
110 template <
typename T>
111 T get_low_register(
int reg)
const;
112 template <
typename T>
113 T get_high_register(
int reg)
const;
114 void set_low_register(
int reg,
uint32_t value);
115 void set_high_register(
int reg,
uint32_t value);
117 double get_double_from_register_pair(
int reg);
118 void set_d_register_from_double(
int dreg,
const double dbl) {
119 DCHECK(dreg >= 0 && dreg < kNumFPRs);
120 *bit_cast<
double*>(&fp_registers_[dreg]) = dbl;
123 double get_double_from_d_register(
int dreg) {
124 DCHECK(dreg >= 0 && dreg < kNumFPRs);
125 return *bit_cast<
double*>(&fp_registers_[dreg]);
127 void set_d_register(
int dreg,
int64_t value) {
128 DCHECK(dreg >= 0 && dreg < kNumFPRs);
129 fp_registers_[dreg] = value;
131 int64_t get_d_register(
int dreg) {
132 DCHECK(dreg >= 0 && dreg < kNumFPRs);
133 return fp_registers_[dreg];
136 void set_d_register_from_float32(
int dreg,
const float f) {
137 DCHECK(dreg >= 0 && dreg < kNumFPRs);
139 int32_t f_int = *bit_cast<int32_t*>(&f);
141 set_d_register(dreg, finalval);
144 float get_float32_from_d_register(
int dreg) {
145 DCHECK(dreg >= 0 && dreg < kNumFPRs);
147 int64_t regval = get_d_register(dreg) >> 32;
148 int32_t regval32 =
static_cast<int32_t
>(regval);
149 return *bit_cast<
float*>(®val32);
153 void set_pc(intptr_t value);
154 intptr_t get_pc()
const;
156 Address get_sp()
const {
return static_cast<Address
>(get_register(sp)); }
164 template <
typename Return,
typename... Args>
165 Return Call(Address entry, Args... args) {
166 return VariadicCall<Return>(
this, &Simulator::CallImpl, entry, args...);
170 void CallFP(Address entry,
double d0,
double d1);
171 int32_t CallFPReturnsInt(Address entry,
double d0,
double d1);
172 double CallFPReturnsDouble(Address entry,
double d0,
double d1);
181 void set_last_debugger_input(
char* input);
182 char* last_debugger_input() {
return last_debugger_input_; }
185 static void SetRedirectInstruction(Instruction* instruction);
188 static bool ICacheMatch(
void* one,
void* two);
189 static void FlushICache(base::CustomMatcherHashMap* i_cache,
void* start,
194 bool has_bad_pc()
const;
197 enum special_values {
208 intptr_t CallImpl(Address entry,
int argument_count,
209 const intptr_t* arguments);
212 void Format(Instruction* instr,
const char* format);
215 bool CarryFrom(int32_t left, int32_t right, int32_t carry = 0);
216 bool BorrowFrom(int32_t left, int32_t right);
217 template <
typename T1>
218 inline bool OverflowFromSigned(T1 alu_out, T1 left, T1 right,
bool addition);
221 int32_t GetShiftRm(Instruction* instr,
bool* carry_out);
222 int32_t GetImm(Instruction* instr,
bool* carry_out);
223 void ProcessPUW(Instruction* instr,
int num_regs,
int operand_size,
224 intptr_t* start_address, intptr_t* end_address);
225 void HandleRList(Instruction* instr,
bool load);
226 void HandleVList(Instruction* inst);
227 void SoftwareInterrupt(Instruction* instr);
230 inline bool isStopInstruction(Instruction* instr);
231 inline bool isWatchedStop(
uint32_t bkpt_code);
232 inline bool isEnabledStop(
uint32_t bkpt_code);
233 inline void EnableStop(
uint32_t bkpt_code);
234 inline void DisableStop(
uint32_t bkpt_code);
235 inline void IncreaseStopCounter(
uint32_t bkpt_code);
239 inline int16_t ByteReverse(int16_t hword);
240 inline int32_t ByteReverse(int32_t word);
244 inline uint8_t ReadBU(intptr_t addr);
245 inline int8_t ReadB(intptr_t addr);
246 inline void WriteB(intptr_t addr, uint8_t value);
247 inline void WriteB(intptr_t addr, int8_t value);
249 inline uint16_t ReadHU(intptr_t addr, Instruction* instr);
250 inline int16_t ReadH(intptr_t addr, Instruction* instr);
252 inline void WriteH(intptr_t addr, uint16_t value, Instruction* instr);
253 inline void WriteH(intptr_t addr, int16_t value, Instruction* instr);
255 inline uint32_t ReadWU(intptr_t addr, Instruction* instr);
256 inline int32_t ReadW(intptr_t addr, Instruction* instr);
257 inline int64_t ReadW64(intptr_t addr, Instruction* instr);
258 inline void WriteW(intptr_t addr,
uint32_t value, Instruction* instr);
259 inline void WriteW(intptr_t addr, int32_t value, Instruction* instr);
261 inline int64_t ReadDW(intptr_t addr);
262 inline double ReadDouble(intptr_t addr);
263 inline float ReadFloat(intptr_t addr);
264 inline void WriteDW(intptr_t addr,
int64_t value);
267 void Trace(Instruction* instr);
270 template <
typename T1,
typename T2>
271 void SetS390RoundConditionCode(T1 r2_val, T2 max, T2 min) {
273 double r2_dval =
static_cast<double>(r2_val);
274 double dbl_min =
static_cast<double>(min);
275 double dbl_max =
static_cast<double>(max);
279 else if (r2_dval < 0.0 && r2_dval >= dbl_min && std::isfinite(r2_dval))
281 else if (r2_dval > 0.0 && r2_dval <= dbl_max && std::isfinite(r2_dval))
287 template <
typename T1>
288 void SetS390RoundConditionCode(T1 r2_val,
int64_t max,
int64_t min) {
290 double r2_dval =
static_cast<double>(r2_val);
291 double dbl_min =
static_cast<double>(min);
292 double dbl_max =
static_cast<double>(max);
304 else if (r2_dval < 0.0 && r2_dval >= dbl_min && std::isfinite(r2_dval))
306 else if (r2_dval > 0.0 && r2_dval < dbl_max && std::isfinite(r2_dval))
313 template <
typename T1,
typename T2,
typename T3>
314 void SetS390ConvertConditionCode(T1 src, T2 dst, T3 max) {
316 if (src == static_cast<T1>(0.0)) {
318 }
else if (src < static_cast<T1>(0.0) && static_cast<T2>(src) == 0 &&
319 std::isfinite(src)) {
321 }
else if (src > static_cast<T1>(0.0) && std::isfinite(src) &&
322 src < static_cast<T1>(max)) {
329 template <
typename T>
330 void SetS390ConditionCode(T lhs, T rhs) {
333 condition_reg_ |= CC_EQ;
334 }
else if (lhs < rhs) {
335 condition_reg_ |= CC_LT;
336 }
else if (lhs > rhs) {
337 condition_reg_ |= CC_GT;
343 if (condition_reg_ == 0) condition_reg_ = unordered;
347 template <
typename T>
348 void SetS390ConditionCodeCarry(T result,
bool overflow) {
350 bool zero_result = (result ==
static_cast<T
>(0));
351 if (zero_result && !overflow) {
353 }
else if (!zero_result && !overflow) {
355 }
else if (zero_result && overflow) {
357 }
else if (!zero_result && overflow) {
360 if (condition_reg_ == 0) UNREACHABLE();
363 bool isNaN(
double value) {
return (value != value); }
369 template <
typename T>
370 void SetS390BitWiseConditionCode(T value) {
374 condition_reg_ |= CC_EQ;
376 condition_reg_ |= CC_LT;
379 void SetS390OverflowCode(
bool isOF) {
380 if (isOF) condition_reg_ = CC_OF;
383 bool TestConditionCode(Condition mask) {
385 if (mask == 0xf)
return true;
387 return (condition_reg_ & mask) != 0;
391 void ExecuteInstruction(Instruction* instr,
bool auto_incr_pc =
true);
394 static void CheckICache(base::CustomMatcherHashMap* i_cache,
396 static void FlushOnePage(base::CustomMatcherHashMap* i_cache, intptr_t start,
398 static CachePage* GetCachePage(base::CustomMatcherHashMap* i_cache,
402 void GetFpArgs(
double* x,
double* y, intptr_t* z);
403 void SetFpResult(
const double& result);
404 void TrashCallerSaveRegisters();
406 void CallInternal(Address entry,
int reg_arg_count = 3);
411 uint64_t registers_[kNumGPRs];
412 int64_t fp_registers_[kNumFPRs];
415 int32_t condition_reg_;
417 intptr_t special_reg_pc_;
421 static const size_t stack_protection_size_ = 256 * kPointerSize;
426 char* last_debugger_input_;
429 Instruction* break_pc_;
436 static const uint32_t kNumOfWatchedStops = 256;
439 static const uint32_t kStopDisabledBit = 1 << 31;
445 struct StopCountAndDesc {
449 StopCountAndDesc watched_stops_[kNumOfWatchedStops];
452 int DecodeInstructionOriginal(Instruction* instr);
453 int DecodeInstruction(Instruction* instr);
454 int Evaluate_Unknown(Instruction* instr);
455 #define MAX_NUM_OPCODES (1 << 16) 456 typedef int (Simulator::*EvaluateFuncType)(Instruction*);
458 static EvaluateFuncType EvalTable[MAX_NUM_OPCODES];
459 static void EvalTableInit();
461 #define EVALUATE(name) int Evaluate_##name(Instruction* instr) 462 #define EVALUATE_VRR_INSTRUCTIONS(name, op_name, op_value) EVALUATE(op_name); 463 S390_VRR_C_OPCODE_LIST(EVALUATE_VRR_INSTRUCTIONS)
464 S390_VRR_A_OPCODE_LIST(EVALUATE_VRR_INSTRUCTIONS)
465 #undef EVALUATE_VRR_INSTRUCTIONS 1204 #endif // defined(USE_SIMULATOR) 1205 #endif // V8_S390_SIMULATOR_S390_H_