Commit efadbfc4 authored by akos.palfi's avatar akos.palfi Committed by Commit bot

MIPS: [Atomics] Remove Atomics code stubs; use TF ops.

Port d412cfa2

BUG=

Review URL: https://codereview.chromium.org/1899783003

Cr-Commit-Position: refs/heads/master@{#35613}
parent 08ef00fd
......@@ -472,6 +472,12 @@ FPUCondition FlagsConditionToConditionCmpFPU(bool& predicate,
__ bind(&done); \
}
#define ASSEMBLE_ATOMIC_LOAD_INTEGER(asm_instr) \
do { \
__ asm_instr(i.OutputRegister(), i.MemoryOperand()); \
__ sync(); \
} while (0)
void CodeGenerator::AssembleDeconstructFrame() {
__ mov(sp, fp);
__ Pop(ra, fp);
......@@ -1325,12 +1331,19 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
UNREACHABLE(); // currently unsupported checked int64 load/store.
break;
case kAtomicLoadInt8:
ASSEMBLE_ATOMIC_LOAD_INTEGER(lb);
break;
case kAtomicLoadUint8:
ASSEMBLE_ATOMIC_LOAD_INTEGER(lbu);
break;
case kAtomicLoadInt16:
ASSEMBLE_ATOMIC_LOAD_INTEGER(lh);
break;
case kAtomicLoadUint16:
ASSEMBLE_ATOMIC_LOAD_INTEGER(lhu);
break;
case kAtomicLoadWord32:
// TODO(binji): implement
__ nop();
ASSEMBLE_ATOMIC_LOAD_INTEGER(lw);
break;
}
} // NOLINT(readability/fn_size)
......
......@@ -1454,7 +1454,7 @@ void InstructionSelector::VisitFloat64InsertHighWord32(Node* node) {
void InstructionSelector::VisitAtomicLoad(Node* node) {
LoadRepresentation load_rep = LoadRepresentationOf(node->op());
OperandGenerator g(this);
MipsOperandGenerator g(this);
Node* base = node->InputAt(0);
Node* index = node->InputAt(1);
ArchOpcode opcode = kArchNop;
......@@ -1472,8 +1472,17 @@ void InstructionSelector::VisitAtomicLoad(Node* node) {
UNREACHABLE();
return;
}
Emit(opcode | AddressingModeField::encode(kMode_MRI),
g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index));
if (g.CanBeImmediate(index, opcode)) {
Emit(opcode | AddressingModeField::encode(kMode_MRI),
g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index));
} else {
InstructionOperand addr_reg = g.TempRegister();
Emit(kMipsAdd | AddressingModeField::encode(kMode_None), addr_reg,
g.UseRegister(index), g.UseRegister(base));
// Emit desired load opcode, using temp addr_reg.
Emit(opcode | AddressingModeField::encode(kMode_MRI),
g.DefineAsRegister(node), addr_reg, g.TempImmediate(0));
}
}
// static
......
......@@ -484,6 +484,12 @@ FPUCondition FlagsConditionToConditionCmpFPU(bool& predicate,
__ bind(&done); \
}
#define ASSEMBLE_ATOMIC_LOAD_INTEGER(asm_instr) \
do { \
__ asm_instr(i.OutputRegister(), i.MemoryOperand()); \
__ sync(); \
} while (0)
void CodeGenerator::AssembleDeconstructFrame() {
__ mov(sp, fp);
__ Pop(ra, fp);
......@@ -1575,12 +1581,19 @@ void CodeGenerator::AssembleArchInstruction(Instruction* instr) {
ASSEMBLE_CHECKED_STORE_FLOAT(Double, sdc1);
break;
case kAtomicLoadInt8:
ASSEMBLE_ATOMIC_LOAD_INTEGER(lb);
break;
case kAtomicLoadUint8:
ASSEMBLE_ATOMIC_LOAD_INTEGER(lbu);
break;
case kAtomicLoadInt16:
ASSEMBLE_ATOMIC_LOAD_INTEGER(lh);
break;
case kAtomicLoadUint16:
ASSEMBLE_ATOMIC_LOAD_INTEGER(lhu);
break;
case kAtomicLoadWord32:
// TODO(binji): implement
__ nop();
ASSEMBLE_ATOMIC_LOAD_INTEGER(lw);
break;
}
} // NOLINT(readability/fn_size)
......
......@@ -1983,8 +1983,17 @@ void InstructionSelector::VisitAtomicLoad(Node* node) {
UNREACHABLE();
return;
}
Emit(opcode | AddressingModeField::encode(kMode_MRI),
g.DefineAsRegister(node), g.UseRegister(base), g.UseRegister(index));
if (g.CanBeImmediate(index, opcode)) {
Emit(opcode | AddressingModeField::encode(kMode_MRI),
g.DefineAsRegister(node), g.UseRegister(base), g.UseImmediate(index));
} else {
InstructionOperand addr_reg = g.TempRegister();
Emit(kMips64Dadd | AddressingModeField::encode(kMode_None), addr_reg,
g.UseRegister(index), g.UseRegister(base));
// Emit desired load opcode, using temp addr_reg.
Emit(opcode | AddressingModeField::encode(kMode_MRI),
g.DefineAsRegister(node), addr_reg, g.TempImmediate(0));
}
}
// static
......
......@@ -2009,6 +2009,10 @@ void Assembler::tne(Register rs, Register rt, uint16_t code) {
emit(instr);
}
void Assembler::sync() {
Instr sync_instr = SPECIAL | SYNC;
emit(sync_instr);
}
// Move from HI/LO register.
......
......@@ -799,6 +799,9 @@ class Assembler : public AssemblerBase {
void teq(Register rs, Register rt, uint16_t code);
void tne(Register rs, Register rt, uint16_t code);
// Memory barrier instruction.
void sync();
// Move from HI/LO register.
void mfhi(Register rd);
void mflo(Register rd);
......
......@@ -409,6 +409,7 @@ enum SecondaryField : uint32_t {
MOVZ = ((1U << 3) + 2),
MOVN = ((1U << 3) + 3),
BREAK = ((1U << 3) + 5),
SYNC = ((1U << 3) + 7),
MFHI = ((2U << 3) + 0),
CLZ_R6 = ((2U << 3) + 0),
......@@ -620,7 +621,6 @@ enum SecondaryField : uint32_t {
NULLSF = 0U
};
// ----- Emulated conditions.
// On MIPS we use this enum to abstract from conditional branch instructions.
// The 'U' prefix is used to specify unsigned comparisons.
......@@ -928,8 +928,7 @@ class Instruction {
FunctionFieldToBitNumber(TEQ) | FunctionFieldToBitNumber(TNE) |
FunctionFieldToBitNumber(MOVZ) | FunctionFieldToBitNumber(MOVN) |
FunctionFieldToBitNumber(MOVCI) | FunctionFieldToBitNumber(SELEQZ_S) |
FunctionFieldToBitNumber(SELNEZ_S);
FunctionFieldToBitNumber(SELNEZ_S) | FunctionFieldToBitNumber(SYNC);
// Get the encoding type of the instruction.
inline Type InstructionType(TypeChecks checks = NORMAL) const;
......
......@@ -1191,6 +1191,9 @@ void Decoder::DecodeTypeRegisterSPECIAL(Instruction* instr) {
case TNE:
Format(instr, "tne 'rs, 'rt, code: 'code");
break;
case SYNC:
Format(instr, "sync");
break;
case MOVZ:
Format(instr, "movz 'rd, 'rs, 'rt");
break;
......
......@@ -3731,6 +3731,9 @@ void Simulator::DecodeTypeRegisterSPECIAL() {
case TNE:
do_interrupt = rs() != rt();
break;
case SYNC:
// TODO(palfia): Ignore sync instruction for now.
break;
// Conditional moves.
case MOVN:
if (rt()) {
......
......@@ -2255,6 +2255,10 @@ void Assembler::tne(Register rs, Register rt, uint16_t code) {
emit(instr);
}
void Assembler::sync() {
Instr sync_instr = SPECIAL | SYNC;
emit(sync_instr);
}
// Move from HI/LO register.
......
......@@ -849,6 +849,9 @@ class Assembler : public AssemblerBase {
void teq(Register rs, Register rt, uint16_t code);
void tne(Register rs, Register rt, uint16_t code);
// Memory barrier instruction.
void sync();
// Move from HI/LO register.
void mfhi(Register rd);
void mflo(Register rd);
......
......@@ -384,6 +384,7 @@ enum SecondaryField : uint32_t {
MOVZ = ((1U << 3) + 2),
MOVN = ((1U << 3) + 3),
BREAK = ((1U << 3) + 5),
SYNC = ((1U << 3) + 7),
MFHI = ((2U << 3) + 0),
CLZ_R6 = ((2U << 3) + 0),
......@@ -645,7 +646,6 @@ enum SecondaryField : uint32_t {
NULLSF = 0U
};
// ----- Emulated conditions.
// On MIPS we use this enum to abstract from conditional branch instructions.
// The 'U' prefix is used to specify unsigned comparisons.
......@@ -964,8 +964,7 @@ class Instruction {
FunctionFieldToBitNumber(TEQ) | FunctionFieldToBitNumber(TNE) |
FunctionFieldToBitNumber(MOVZ) | FunctionFieldToBitNumber(MOVN) |
FunctionFieldToBitNumber(MOVCI) | FunctionFieldToBitNumber(SELEQZ_S) |
FunctionFieldToBitNumber(SELNEZ_S);
FunctionFieldToBitNumber(SELNEZ_S) | FunctionFieldToBitNumber(SYNC);
// Get the encoding type of the instruction.
inline Type InstructionType(TypeChecks checks = NORMAL) const;
......
......@@ -1387,6 +1387,9 @@ void Decoder::DecodeTypeRegisterSPECIAL(Instruction* instr) {
case TNE:
Format(instr, "tne 'rs, 'rt, code: 'code");
break;
case SYNC:
Format(instr, "sync");
break;
case MOVZ:
Format(instr, "movz 'rd, 'rs, 'rt");
break;
......
......@@ -3819,6 +3819,9 @@ void Simulator::DecodeTypeRegisterSPECIAL() {
case TNE:
do_interrupt = rs() != rt();
break;
case SYNC:
// TODO(palfia): Ignore sync instruction for now.
break;
// Conditional moves.
case MOVN:
if (rt()) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment