Преглед на файлове

Added basic support for CAS instructions

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@6376 8c9fc860-2736-0410-a75d-ab315db34111
eth.negelef преди 9 години
родител
ревизия
58a688deaf
променени са 1 файла, в които са добавени 27 реда и са изтрити 0 реда
  1. 27 0
      source/FoxARMBackend.Mod

+ 27 - 0
source/FoxARMBackend.Mod

@@ -64,6 +64,7 @@ CONST
 	opFUITOD = InstructionSet.opFUITOD; opFUITOS = InstructionSet.opFUITOS;
 	opLDC = InstructionSet.opLDC; opLDC2 = InstructionSet.opLDC2;
 	opLDM = InstructionSet.opLDM; opLDR = InstructionSet.opLDR;
+	opLDREX = InstructionSet.opLDREX; opSTREX = InstructionSet.opSTREX;
 	opMCR = InstructionSet.opMCR; opMCR2 = InstructionSet.opMCR2;
 	opMCRR = InstructionSet.opMCRR; opMLA = InstructionSet.opMLA;
 	opMOV = InstructionSet.opMOV; opMRC = InstructionSet.opMRC;
@@ -1382,6 +1383,7 @@ TYPE
 			| IntermediateCode.shr: EmitShiftOrRotation(irInstruction)
 			| IntermediateCode.rol: EmitShiftOrRotation(irInstruction)
 			| IntermediateCode.ror: EmitShiftOrRotation(irInstruction)
+			| IntermediateCode.cas: EmitCas(irInstruction);
 			| IntermediateCode.copy: EmitCopy(irInstruction)
 			| IntermediateCode.fill: EmitFill(irInstruction, FALSE)
 			| IntermediateCode.asm: EmitAsm(irInstruction)
@@ -2930,6 +2932,31 @@ TYPE
 			Emit1(opSWI, InstructionSet.NewImmediate(LONGINT(irInstruction.op1.intValue))) (* software interrupt *)
 		END EmitTrap;
 
+		PROCEDURE EmitCas(VAR irInstruction: IntermediateCode.Instruction);
+		VAR
+			addressReg, addressBaseReg, comparandReg, comparandBaseReg, comparatorReg, comparatorBaseReg, tempReg: Operand
+		BEGIN
+			addressReg := GetFreeRegister(IntermediateCode.UnsignedIntegerType(32));
+			addressBaseReg := RegisterFromIrOperand(irInstruction.op1, Low, addressReg);
+			MovIfDifferent(addressReg, addressBaseReg);
+			IF IntermediateCode.OperandEquals (irInstruction.op2, irInstruction.op3) THEN
+				Emit2(opLDR, opRES, InstructionSet.NewImmediateOffsetMemory(addressReg.register, 0, {InstructionSet.Increment}));
+			ELSE
+				comparandReg := GetFreeRegister(IntermediateCode.UnsignedIntegerType(32));
+				comparandBaseReg := RegisterFromIrOperand(irInstruction.op2, Low, comparandReg);
+				MovIfDifferent(comparandReg, comparandBaseReg);
+				comparatorReg := GetFreeRegister(IntermediateCode.UnsignedIntegerType(32));
+				comparatorBaseReg := RegisterFromIrOperand(irInstruction.op3, Low, comparatorReg);
+				MovIfDifferent(comparatorReg, comparatorBaseReg);
+				Emit2(opLDREX, opRES, addressReg);
+				Emit2(opCMP, opRES, comparandReg);
+				tempReg := GetFreeRegister(IntermediateCode.UnsignedIntegerType(32));
+				Emit3WithCondition(opSTREX, tempReg, comparatorReg, addressReg, InstructionSet.conditionEQ);
+				Emit2WithCondition(opCMP, tempReg, InstructionSet.NewImmediate(1), InstructionSet.conditionEQ);
+				Emit1WithCondition(opB, InstructionSet.NewImmediate (-24), InstructionSet.conditionEQ);
+			END;	
+		END EmitCas;
+
 		(* possible optimization: use a combination of LDR and LDRB (would be 4x faster on average) *)
 		PROCEDURE EmitCopy(VAR irInstruction: IntermediateCode.Instruction);
 		VAR