IDENTIFICATION DIVISION.
	PROGRAM-ID. M99.
	DATE-WRITTEN. 18/11/2022.
	AUTHOR. Hippolyte Damay--Glorieux.
ENVIRONMENT DIVISION.
	INPUT-OUTPUT SECTION.
		FILE-CONTROL.
			SELECT ROM ASSIGN TO 'ram.m99'.
DATA DIVISION.
	FILE SECTION.
		FD	ROM.
			01	ROM_FILE.
				05	INSTRUCTIONS	PIC X(400).
	WORKING-STORAGE SECTION.
		01	MEMOIRE.
			05	MEM_CELLULE 			OCCURS 100 TIMES INDEXED BY PC.
				06	CONTENU				PIC 999.
				06	FILLER				PIC X.
		01	TABLEAU REDEFINES MEMOIRE	USAGE IS DISPLAY.
			05	TAB_LIGNE 				OCCURS 10 TIMES.
				10 	TAB_COLONNE			OCCURS 10 TIMES.
					15	TAB_CELLULE		PIC 999.
					15	FILLER 			PIC X.
		77	A 							PIC 999.
		77	B 							PIC 999.
		77	R 							PIC 999.
		77	IDX							PIC 999.
		77	ENTREE						PIC 999.
		01	INSTRUCTION.
			02	OPCODE					PIC 9.
				88	STR					VALUE 0.
				88	LDA					VALUE 1.
				88	LDB					VALUE 2.
				88	MOV					VALUE 3.
				88	CAL					VALUE 4.
				88	JMP					VALUE 5.
				88	JPP					VALUE 6.
				88	JEQ					VALUE 7.
				88	JNE					VALUE 8.
			02	ARGS.
				03	ARG1				PIC 9.
				03	ARG2				PIC 9.
		77	FILLER						PIC 9 	VALUE ZERO.
			88	EOF						VALUE 1.
		01	CONFIG.
			02	PAS_A_PAS				PIC 9.
				88	DEBUG				VALUE 1.
			02	DEBUT					PIC 999	VALUE ZEROES.
	SCREEN SECTION.
		01	PLA_TAB.
			02	LINE 1 COL 1 VALUE "=======================================".
			02	LINE 2 COL 1 PIC A(39) FROM TAB_LIGNE(1).
			02	LINE 3 COL 1 VALUE "=======================================".
			02	LINE 4 COL 1 PIC A(39) FROM TAB_LIGNE(2).
			02	LINE 5 COL 1 VALUE "=======================================".
			02	LINE 6 COL 1 PIC A(39) FROM TAB_LIGNE(3).
			02	LINE 7 COL 1 VALUE "=======================================".
			02	LINE 8 COL 1 PIC A(39) FROM TAB_LIGNE(4).
			02	LINE 9 COL 1 VALUE "=======================================".
			02	LINE 10 COL 1 PIC A(39) FROM TAB_LIGNE(5).
			02	LINE 11 COL 1 VALUE "=======================================".
			02	LINE 12 COL 1 PIC A(39) FROM TAB_LIGNE(6).
			02	LINE 13 COL 1 VALUE "=======================================".
			02	LINE 14 COL 1 PIC A(39) FROM TAB_LIGNE(7).
			02	LINE 15 COL 1 VALUE "=======================================".
			02	LINE 16 COL 1 PIC A(39) FROM TAB_LIGNE(8).
			02	LINE 17 COL 1 VALUE "=======================================".
			02	LINE 18 COL 1 PIC A(39) FROM TAB_LIGNE(9).
			02	LINE 19 COL 1 VALUE "=======================================".
			02	LINE 20 COL 1 PIC A(39) FROM TAB_LIGNE(10).
			02	LINE 21 COL 1 VALUE "=======================================".
		01	PLA_REG.
			02	LINE 24	COL 1 VALUE "A: ".
			02	LINE 24	COL 4 PIC 999 FROM A.
			02	LINE 25	COL 1 VALUE "B: ".
			02	LINE 25	COL 4 PIC 999 FROM B.
			02	LINE 26	COL 1 VALUE "R: ".
			02	LINE 26	COL 4 PIC 999 FROM R.
			02	LINE 27	COL 1 VALUE	"INSTRUCTION: ".
			02	LINE 27	COL 15 PIC 999 FROM INSTRUCTION.
			02	LINE 28	COL 1 VALUE "PC: ".
			02	LINE 28 COL 5 PIC 999 FROM PC.
		01	PLA_OUT.
			02	LINE 23	COL 40 VALUE "Output :".
			02	LINE 23	COL 51 FROM TAB_CELLULE(10, 10).
		01	PLS_CFG.
			02	LINE 1	COL 1 VALUE "Debug (0:non, 1:oui): ".
			02	LINE 1	COL 23 TO PAS_A_PAS.
			02	LINE 2	COL 1 VALUE "Debut: ".
			02	LINE 2	COL 8 PIC 99 TO DEBUT.
		01	PLS_INP.
			02	LINE 24 COL 40 VALUE "Input :".
			02	LINE 24	COL 48 PIC 999 TO ENTREE.
		01	PLS_BLK.
			02	BLANK SCREEN.
		01	PLS_SLP.
			02	LINE 27	COL 40 VALUE "Nouvelle iteration".
			02	LINE 27	COL 60 PIC 9 TO ENTREE.
PROCEDURE DIVISION.
	OPEN INPUT ROM
		READ ROM INTO INSTRUCTIONS
			NOT AT END MOVE INSTRUCTIONS TO MEMOIRE
		END-READ
	CLOSE ROM.
	ACCEPT PLS_CFG.	
	SET PC TO DEBUT.
	ADD 1 TO PC.
	DISPLAY PLA_TAB.
	PERFORM UNTIL EOF
		MOVE CONTENU(PC) TO INSTRUCTION
		COMPUTE IDX = ARG1 * 10 + (ARG2 + 1)

		EVALUATE TRUE
			WHEN STR
				MOVE R TO MEM_CELLULE(IDX)
			WHEN LDA
				IF IDX IS EQUAL TO 100 THEN
					ACCEPT PLS_INP
					MOVE ENTREE TO A
				ELSE
					MOVE MEM_CELLULE(IDX) TO A
				END-IF
			WHEN LDB
				IF IDX IS EQUAL TO 100 THEN
					ACCEPT PLS_INP
					MOVE ENTREE TO B	
				ELSE
					MOVE MEM_CELLULE(IDX) TO B
				END-IF
			WHEN MOV
				IF ARG1 IS EQUAL 0 THEN
					IF ARG2 IS EQUAL 1 THEN
						MOVE R TO A
					ELSE IF ARG2 IS EQUAL 2 THEN
						MOVE R TO B
					END-IF
				ELSE IF ARG1 IS EQUAL 1 THEN
					IF ARG2 IS EQUAL 2 THEN
						MOVE A TO B
					ELSE IF ARG2 IS EQUAL 0 THEN
						MOVE A TO R
					END-IF
				ELSE IF ARG1 IS EQUAL 2 THEN
					IF ARG2 IS EQUAL 0 THEN
						MOVE B TO R
					ELSE IF ARG2 IS EQUAL 1 THEN
						MOVE B TO A
					END-IF
				END-IF
			WHEN CAL
				IF ARG2 IS EQUAL ZERO THEN
					ADD A TO B GIVING R
				ELSE IF ARG2 IS EQUAL 1 THEN
					IF B IS GREATER THAN A THEN
						MOVE ZEROES TO R
					ELSE
						MOVE A TO R SUBTRACT B FROM R
					END-IF
				END-IF
			WHEN JMP
				SUBTRACT 1 FROM IDX
				MOVE IDX TO PC
			WHEN JPP
				SUBTRACT 1 FROM IDX
				IF R IS GREATER THAN 0 THEN
					MOVE IDX TO PC
				END-IF 
			WHEN JEQ
				IF R IS EQUAL IDX THEN
					SET PC UP BY 1
				END-IF
			WHEN JNE
				IF R IS NOT EQUAL IDX THEN
					SET PC UP BY 1
				END-IF
			WHEN OTHER
				SET EOF TO TRUE
		END-EVALUATE
		IF MEM_CELLULE(100) IS NOT EQUAL ZEROES THEN
			DISPLAY PLA_OUT
			MOVE ZEROES TO MEM_CELLULE(100)
		END-IF
		DISPLAY PLA_REG, PLA_TAB
		IF DEBUG THEN 
			ACCEPT PLS_SLP 
		END-IF
		IF PC IS EQUAL 100 THEN
			SET EOF TO TRUE		
		ELSE
			SET PC UP BY 1
		END-IF
	END-PERFORM.
	STOP RUN.
