浏览代码

parsing of RXB / additional operand encoding, up to 5 operands

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@7535 8c9fc860-2736-0410-a75d-ab315db34111
felixf 7 年之前
父节点
当前提交
0c3a209bc5
共有 2 个文件被更改,包括 73 次插入18 次删除
  1. 10 4
      source/FoxAMD64Assembler.Mod
  2. 63 14
      source/FoxAMD64InstructionSet.Mod

+ 10 - 4
source/FoxAMD64Assembler.Mod

@@ -308,7 +308,8 @@ TYPE
 					FOR i := 0 TO maxNumberOperands - 1 DO
 						IF (i>=LEN(operands)) OR (operands[i].type = none) THEN (* no operand -> check if instruction has no operand here *)
 							IF InstructionSet.instructions[instr].operands[i] # none THEN
-							RETURN FALSE END;
+								RETURN FALSE 
+							END;
 						ELSIF ~Matches(operands[i],InstructionSet.instructions[instr].operands[i]) THEN (* instruction operand type and this operand do not match *)
 							RETURN FALSE
 						ELSIF (cpuBits = bits64) & (InstructionSet.optNot64 IN InstructionSet.instructions[instr].bitwidthOptions) THEN (* instruction is invalid in 64 bit mode *)
@@ -319,8 +320,9 @@ TYPE
 				END MatchesInstruction;
 			BEGIN
 				instr := InstructionSet.mnemonics[mnem].firstInstruction;
-
-				WHILE (instr <= InstructionSet.mnemonics[mnem].lastInstruction) & (~MatchesInstruction ()) DO INC (instr); END;
+				WHILE (instr <= InstructionSet.mnemonics[mnem].lastInstruction) & (~MatchesInstruction ()) DO 
+					INC (instr); 
+				END;
 
 				IF instr > InstructionSet.mnemonics[mnem].lastInstruction THEN
 					ErrorSI("invalid combination of opcode and operands", mnem,operands); RETURN none;
@@ -965,11 +967,15 @@ TYPE
 		END EmitPrefix;
 
 		PROCEDURE Emit*(mnem: LONGINT; VAR op1,op2,op3: Operand);
-		VAR operands: ARRAY maxNumberOperands OF Operand; res: BOOLEAN;
+		VAR operands: ARRAY maxNumberOperands OF Operand; res: BOOLEAN; i: LONGINT; noOperand: Operand;
 		BEGIN
 			operands[0] := op1;
 			operands[1] := op2;
 			operands[2] := op3;
+			noOperand.type := none;
+			FOR i := 3 TO maxNumberOperands-1 DO
+				operands[i] := noOperand;
+			END;
 			res := EmitInstruction(mnem,operands,TRUE);
 			op1 := operands[0];
 			op2 := operands[1];

+ 63 - 14
source/FoxAMD64InstructionSet.Mod

@@ -29,13 +29,13 @@ IMPORT KernelLog (* debugging *);
 
 CONST
 	maxCPUs* = 30;
-	maxNumberOperands*=3; (* maximal two source and one destination operand *)
+	maxNumberOperands*=5; (* maximal two source and one destination operand *)
 
 	(* numbers generated by the instruction set parser *)
 	maxNumberMnemonics = 1008;
 	maxNumberInstructions = 3380;
 	maxMnemonicNameLength =20;
-	maxCodeLength* =10;
+	maxCodeLength* =12;
 	none* = -1;
 
 	bitsDefault*=0;
@@ -201,6 +201,7 @@ CONST
 	xmmmem8*=74;
 	xmmmem16*=75;
 	reg32mem16*=76;
+	m2z*=77;
 
 	(** prefixes **)
 	prfOP* = 066H;
@@ -1346,6 +1347,7 @@ CONST
 	opCode*= 0; modRMExtension*= 1; modRMBoth*= 2; cb*= 3; cw*= 4; cd*= 5; cp*= 6; ib*= 7;
 	iw*= 8; id*= 9; iq*= 10; rb*= 11; rw*= 12; rd*= 13; rq*= 14; mem64Operand*= 15;
 	mem128Operand*= 16; fpStackOperand*= 17; directMemoryOffset*= 18;
+	Src1Prefix* = 19; Src2Prefix* = 20; CountPrefix*= 21; DestPrefix*=22; RXB*=23;
 
 TYPE
 	Name = ARRAY 20 OF CHAR;
@@ -1521,6 +1523,7 @@ VAR
 					ELSIF name = "xmm1" THEN RETURN xmm;
 					ELSIF name = "xmm2" THEN RETURN xmm;
 					ELSIF name = "xmm3" THEN RETURN xmm;
+					ELSIF name = "xmm4" THEN RETURN xmm;
 					ELSIF name = "xmm/mem32" THEN RETURN xmmmem32;
 					ELSIF name = "xmm/mem64" THEN RETURN xmmmem64;
 					ELSIF name = "xmm/mem128" THEN RETURN xmmmem128;
@@ -1537,6 +1540,9 @@ VAR
 					ELSIF name = "xmm3/mem32" THEN RETURN xmmmem32;
 					ELSIF name = "xmm3/mem64" THEN RETURN xmmmem64;
 					ELSIF name = "xmm3/mem128" THEN RETURN xmmmem128;
+					ELSIF name = "xmm4/mem32" THEN RETURN xmmmem32;
+					ELSIF name = "xmm4/mem64" THEN RETURN xmmmem64;
+					ELSIF name = "xmm4/mem128" THEN RETURN xmmmem128;
 					ELSIF name = "mmx/mem64" THEN RETURN mmxmem64;
 					ELSIF name = "mmx1" THEN RETURN mmx;
 					ELSIF name = "mmx2" THEN RETURN mmx;
@@ -1566,10 +1572,12 @@ VAR
 					ELSIF name = "ymm2/mem128" THEN RETURN ymmmem128;
 					ELSIF name = "ymm2/m128" THEN RETURN ymmmem128;
 					ELSIF name = "ymm3/mem128" THEN RETURN ymmmem128;
+					ELSIF name = "ymm4/mem256" THEN RETURN ymmmem256;
 					ELSIF name = "vm32x" THEN RETURN vm32x
 					ELSIF name = "vm32y" THEN RETURN vm32y
 					ELSIF name = "vm64x" THEN RETURN vm64x
 					ELSIF name = "vm64y" THEN RETURN vm64y
+					ELSIF name = "m2z" THEN RETURN m2z
 					ELSE HALT(200) 
 					END;
 				END StringToOperand;
@@ -1728,27 +1736,67 @@ VAR
 				RETURN TRUE;
 			END GetCode;
 		
-		VAR i,k,length: SHORTINT; ch1,ch2: CHAR; cdc: ARRAY 32 OF CHAR; at: LONGINT;
+		VAR i,k,length: SHORTINT; ch1,ch2: CHAR; cdc: ARRAY 32 OF CHAR; at,mul,val: LONGINT;
 		BEGIN
 			i := 0; k := 0; at := 0;
 			WHILE(GetCode(charcode,at,cdc)) DO
 				ch1 := cdc[0];
 				ch2 := cdc[1];
 				IF (ch2 = ".") & ((ch1="0") OR (ch1="1") OR (ch1="X")) THEN
-					
+					mul := 80H;
+					val := 0;
+					i := 0;
+					code[k] := CHR(opCode);
+					WHILE (cdc[i] # 0X) DO
+						IF (cdc[i] ="0") OR (cdc[i]="X") THEN
+							mul := mul DIV 2;
+						ELSIF cdc[i] = "1" THEN
+							INC(val, mul); 
+							mul := mul DIV 2;
+						ELSIF cdc[i] = "." (* next *) THEN
+						ELSIF cdc[i] = "c" THEN
+							INC(i); ASSERT(cdc[i] ="o"); 
+							INC(i); ASSERT(cdc[i] ="u");
+							INC(i); ASSERT(cdc[i] ="n");
+							INC(i); ASSERT(cdc[i] ="t");
+							code[k] := CHR(CountPrefix);
+						ELSIF cdc[i] = "d" THEN
+							INC(i); ASSERT(cdc[i] ="e"); 
+							INC(i); ASSERT(cdc[i] ="s");
+							INC(i); ASSERT(cdc[i] ="t");
+							code[k] := CHR(DestPrefix);
+						ELSIF cdc[i] = "s" THEN
+							INC(i); ASSERT(cdc[i] ="r"); 
+							INC(i); ASSERT(cdc[i] ="c");
+							code[k] := CHR(Src1Prefix);
+							ASSERT(mul = 64); 
+							IF (cdc[i+1] = "1") THEN 
+								INC(i);
+							ELSIF (cdc[i+1] = "2") THEN 
+								code[k] := CHR(Src2Prefix);
+								INC(i);
+							END;
+						ELSE HALT(100);
+						END;
+						INC(i);
+					END;
+					INC(k);
+					code[k] := CHR(val); INC(k);
 				ELSIF (ch1="R") THEN
-					IF cdc = "RXB.00001" THEN
-					ELSIF cdc ="RXB.00011" THEN
-					ELSIF cdc ="RXB.00010" THEN
-					ELSIF cdc ="RXB.01000" THEN
-					ELSIF cdc ="RXB.01" THEN
-					ELSIF cdc ="RXB.02" THEN
-					ELSIF cdc ="RXB.2" THEN
-					ELSIF cdc ="RXB.03" THEN
-					ELSIF cdc ="RXB.08" THEN
+					code[k] := CHR(RXB); INC(k); 
+					IF (cdc = "RXB.00001") OR  (cdc ="RXB.01") THEN
+						code[k] := CHR(1);
+					ELSIF (cdc ="RXB.00011") OR (cdc = "RXB.03") THEN
+						code[k] := CHR(3);
+					ELSIF (cdc ="RXB.00010") OR (cdc = "RXB.2") OR (cdc = "RXB.02") THEN
+						code[k] := CHR(2);
+					ELSIF (cdc ="RXB.01000") OR (cdc ="RXB.08") THEN
+						code[k] := CHR(8);
 					ELSIF cdc ="RXB.09" THEN
+						code[k] := CHR(9);
 					ELSE HALT(100)
 					END;
+					INC(k);
 				ELSE
 				CASE ch1 OF
 					'0'..'9','A'..'F':
@@ -1767,7 +1815,7 @@ VAR
 							ELSIF cdc = "/is4" THEN 
 								(*todo*)
 							ELSIF cdc = "/ib" THEN 
-								(*todo*)
+								code[k] := CHR(ib); INC(k);
 							ELSE
 								HALT(100)
 							END;
@@ -1835,6 +1883,7 @@ VAR
 				instructions[numberInstructions].operands[i] := ParseOperand(operands,at);
 				INC(i);
 			END;
+			ASSERT(operands[at] = 0X); (* all operands parsed *)
 			
 			EncodeV(code,instructions[numberInstructions].code);