seq-std.hcl is the HCL for the standard, sequential Y86 simulator. seq-inc.hcl is the HCL for a simulator that supports the "incl" instruction: incl rA opcode is C0 registers specified are rA, RNONE (8) This instruction adds 1 to any register, storing the result in the register file (and setting CC bits). Steps for incl instruction are shown below: FETCH: icode:ifun <- M1[PC] # get 1st byte of instruction rA:rB <- M1[PC+1] # rA is part of instruction, rB is 8 valP <- PC+2 # next instruction is 2 bytes away DECODE: valA <- R[rA] # rA is the register to increment # we don't use valB EXECUTE: valE <- valA + 1 # add 1 to valA set CC # set CC flags MEMORY: # nothing WRITE BACK: R[rA] <- valE # store result in register rA PC UPDATE: PC <- valP # always the next instruction ============================================================================ To support this new instruction, we need to make some changes to the HCL file. I first made a copy of seq-std.hcl named seq-inc.hcl and added support for the new instruction as shown below (anything not mentioned was unchanged from seq-std.hcl): # added definition if IINCL: intsig IINCL 'I_INCL' # IINCL needs register ids read (second byte of instruction), so # need_regids must be changed to: # Does fetched instruction require a regid byte? bool need_regids = icode in { IRRMOVL, IOPL, IPUSHL, IPOPL, IIRMOVL, IRMMOVL, IMRMOVL, IINCL}; # IINCL is a new valid opcode, so it must be added to instr_valid: bool instr_valid = icode in { INOP, IHALT, IRRMOVL, IIRMOVL, IRMMOVL, IMRMOVL, IOPL, IJXX, ICALL, IRET, IPUSHL, IPOPL, IINCL }; # in decode stage for IINCL, we need to set srcA to be our register rA: ## What register should be used as the A source? int srcA = [ icode in { IRRMOVL, IRMMOVL, IOPL, IPUSHL, IINCL } : rA; icode in { IPOPL, IRET } : RESP; 1 : RNONE; # Don't need register ]; # rA is also the register that should be written during write back # with the value of valE, so we need to change dstE: ## What register should be used as the E destination? int dstE = [ icode in { IINCL} : rA; icode in { IRRMOVL, IIRMOVL, IOPL, IINCL} : rB; icode in { IPUSHL, IPOPL, ICALL, IRET } : RESP; 1 : RNONE; # Don't need register ]; # during execute we want to add 1 and rA, we feed rA via aluA and # a 1 via aluB: ################ Execute Stage ################################### ## Select input A to ALU int aluA = [ icode in { IRRMOVL, IOPL, IINCL } : valA; icode in { IIRMOVL, IRMMOVL, IMRMOVL } : valC; icode in { ICALL, IPUSHL } : -4; icode in { IRET, IPOPL } : 4; # Other instructions don't need ALU ]; ## Select input B to ALU int aluB = [ icode in { IRMMOVL, IMRMOVL, IOPL, ICALL, IPUSHL, IRET, IPOPL } : valB; icode in { IINCL } : 1; icode in { IRRMOVL, IIRMOVL } : 0; # Other instructions don't need ALU ]; # note that the default ALU function is add, this is fine (we don't need # to change this). # we do set condition codes, so add IINCL to set_cc: ## Should the condition codes be updated? bool set_cc = icode in { IOPL, IINCL }; # nothing else needs to be changed! ============================================================================ Next step is to build the simulator based on this new HCL code (now in seq-inc.hcl). The Makefile already has the rules for this, so all you need to do is type "make sinc" (sinc is the name of the new simulator). To test the code, I've modified a version of the asum.ys program to use this new incl instruction. This modified source is included here as asum-inc.ys. To assemble it: ./yas asum-inc.ys Make sure you use the version of yas in this directory. To run the asum-inc program: ./sinc asum-inc.yo behavior should be the same as when we played with this program in lab 8, that is, register eax should contain 0x0000abcd when the program halts. ============================================================================