void branchControl(uint64_t ir){ if(ir == 0){ turnON(END_FLAG); }else if ((ir == 13)||(ir == 14)){ turnON(FETCH_FLAG); if(ir == 14){ turnON(JMPR_FLAG); } setReg(PC,getReg(MAR)); }else if ((ir == 15)||(ir == 16)){ if(getReg(MBR) == 0){ turnON(FETCH_FLAG); if(ir == 16){ turnON(JMPR_FLAG); } setReg(PC,getReg(MAR)); } } }
uint16_t AnalogToDigitalConverter::sample(byte channel) { //while(getReg(ADCSRA,(1<<ADSC))); // Wait for prior sample clearAndSetReg(ADMUX,AnalogMuxMask,channel); assignReg(ADCSRA,(1<<ADSC),1); while(getReg(ADCSRA,(1<<ADSC))); // Wait for prior sample uint16_t result = ADCL; result = result | (((uint16_t)(ADCH))<<8); return result; }
/* ** =================================================================== ** Method : SCI1_Init (component Init_SCI) ** ** Description : ** This method initializes registers of the SCI module ** according to this Peripheral Initialization Bean settings. ** Call this method in the user code to initialize the ** module. By default, the method is called by PE ** automatically; see "Call Init method" property of the ** bean for more details. ** Parameters : None ** Returns : Nothing ** =================================================================== */ void SCI1_Init(void) { getReg(SCI_STAT); /* Clear interrupt request flags */ /* SCI_RATE: SBR=26,FRAC_SBR=0 */ setReg16(SCI_RATE,208U); /* Set prescaler bits */ /* SCI_CTRL1: LOOP=0,SWAI=0,RSRC=0,M=0,WAKE=0,POL=0,PE=0,PT=0,TEIE=0,TIIE=0,RFIE=1,REIE=0,TE=1,RE=1,RWU=0,SBK=0 */ setReg16(SCI_CTRL1,44U); /* Set the SCI control register */ /* SCI_CTRL2: TFCNT=0,TFWM=0,RFCNT=0,RFWM=0,FIFO_EN=0,??=0,LIN_MODE=0,??=0,??=0,??=0 */ setReg16(SCI_CTRL2,0U); /* Set the SCI control register */ }
void AD_interruptCCA(void) { _sample_A[0] = (getReg(ADCA_ADRSLT0)); _sample_A[1] = (getReg(ADCA_ADRSLT1)); _sample_A[2] = (getReg(ADCA_ADRSLT2)); // _sample_A[3] = (getReg(ADCA_ADRSLT3)); // _sample_A[4] = (getReg(ADCA_ADRSLT4)); // _sample_A[5] = (getReg(ADCA_ADRSLT5)); _sample_A[6] = (getReg(ADCA_ADRSLT6)); _sample_A[7] = (getReg(ADCA_ADRSLT7)); setReg(ADCA_ADSTAT, 0x0800); /* Clear EOSI flag */ OutFlgA = TRUE; /* Measured values are available */ if (!(getRegBit(ADCA_ADCR1, SMODE2))) { /* Not running in trigger mode? */ ad_ModeFlgA = IDLE; /* Set the bean to the idle mode */ } }
static DecodeStatus DecodeLO32DSPRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, MCRegisterInfo *Decoder) { if (RegNo >= 4) return MCDisassembler_Fail; unsigned Reg = getReg(Decoder, Mips_LO32DSPRegClassID, RegNo); MCInst_addOperand(Inst, MCOperand_CreateReg(Reg)); return MCDisassembler_Success; }
int DS1621::getHrTemp() { startConversion(true); // initiate conversion uint8_t cfg = 0; while (!(cfg & DONE)) { // let it finish cfg = getReg(ACCESS_CFG); } int tHR = getTemp(RD_TEMP); // get whole degrees reading uint8_t cRem = getReg(RD_CNTR); // get counts remaining uint8_t slope = getReg(RD_SLOPE); // get counts per degree if (tHR >= 0) tHR = (tHR * 100 - 25) + ((slope - cRem) * 100 / slope); else { tHR = -tHR; tHR = (-25 - tHR * 100) + ((slope - cRem) * 100 / slope); } return tHR; }
static DecodeStatus DecodeMem(MCInst *Inst, unsigned Insn, uint64_t Address, MCRegisterInfo *Decoder) { int Offset = SignExtend32(Insn & 0xffff, 16); unsigned Reg = fieldFromInstruction(Insn, 16, 5); unsigned Base = fieldFromInstruction(Insn, 21, 5); Reg = getReg(Decoder, Mips_GPR32RegClassID, Reg); Base = getReg(Decoder, Mips_GPR32RegClassID, Base); if (MCInst_getOpcode(Inst) == Mips_SC){ MCOperand_CreateReg0(Inst, Reg); } MCOperand_CreateReg0(Inst, Reg); MCOperand_CreateReg0(Inst, Base); MCOperand_CreateImm0(Inst, Offset); return MCDisassembler_Success; }
void PWMBReload_Interrupt(void) { //clear the interrupt flag of the pwm reload interrupt clrRegBits(PWMB_PMCTL, PWMB_PMCTL_PWMF_MASK); //read the hall sensors status1=HALLSENSOR1; if (old_status1!= status1) { if (status1 == DIRECTION_TABLE[old_status1]) { comm_enc[1]++; // phase_changed[1]=1; // write mask to PWM Channel Control Register PWMState[1]= pTable1[status1]; tmp = getReg(PWMB_PMOUT) & 0x8000; val=tmp | PWMState[1].MaskOut | (PWMState[1].Mask<<8); setReg(PWMB_PMOUT,val); old_status1 = status1; } else if (status1 == DIRECTION_TABLE_INV[old_status1]) { comm_enc[1]--; // phase_changed[1]=1; // write mask to PWM Channel Control Register PWMState[1]= pTable1[status1]; tmp = getReg(PWMB_PMOUT) & 0x8000; val=tmp | PWMState[1].MaskOut | (PWMState[1].Mask<<8); setReg(PWMB_PMOUT,val); old_status1 = status1; } else { hall_error[1]=HALL_ERROR_TABLE; PWM_outputPadDisable(1); #ifdef DEBUG_CAN_MSG can_printf("HALL ERROR 1"); #endif } } }
static DecodeStatus DecodeFGRCCRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, MCRegisterInfo *Decoder) { unsigned Reg; if (RegNo > 31) return MCDisassembler_Fail; Reg = getReg(Decoder, Mips_FGRCCRegClassID, RegNo); MCOperand_CreateReg0(Inst, Reg); return MCDisassembler_Success; }
static DecodeStatus DecodeRRegsRegisterClass(MCInst *Inst, unsigned RegNo, uint64_t Address, void *Decoder) { unsigned Reg; if (RegNo > 15) return MCDisassembler_Fail; Reg = getReg(Decoder, XCore_RRegsRegClassID, RegNo); MCOperand_CreateReg0(Inst, Reg); return MCDisassembler_Success; }
void digitalWrite(const PIN pin, unsigned int value) { unsigned long addr; unsigned long bitMask; pinToMem(pin, &addr, &bitMask); unsigned long reg = getReg(addr + GPIO_DATAOUT); if (value) reg = setBit(reg, bitMask); else reg = clearBit(reg, bitMask); setReg(addr + GPIO_DATAOUT,reg); }
static DecodeStatus DecodeBlezGroupBranch_4(MCInst *MI, uint32_t insn, uint64_t Address, MCRegisterInfo *Decoder) { // If we are called then we can assume that MIPS32r6/MIPS64r6 is enabled // (otherwise we would have matched the BLEZL instruction from the earlier // ISA's instead). // // We have: // 0b000110 sssss ttttt iiiiiiiiiiiiiiii // Invalid if rs == 0 // BLEZALC if rs == 0 && rt != 0 // BGEZALC if rs == rt && rt != 0 // BGEUC if rs != rt && rs != 0 && rt != 0 uint32_t Rs = fieldFromInstruction(insn, 21, 5); uint32_t Rt = fieldFromInstruction(insn, 16, 5); uint32_t Imm = (uint32_t)SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4; bool HasRs = false; if (Rt == 0) return MCDisassembler_Fail; else if (Rs == 0) MCInst_setOpcode(MI, Mips_BLEZALC); else if (Rs == Rt) MCInst_setOpcode(MI, Mips_BGEZALC); else { HasRs = true; MCInst_setOpcode(MI, Mips_BGEUC); } if (HasRs) MCOperand_CreateReg0(MI, getReg(Decoder, Mips_GPR32RegClassID, Rs)); MCOperand_CreateReg0(MI, getReg(Decoder, Mips_GPR32RegClassID, Rt)); MCOperand_CreateImm0(MI, Imm); return MCDisassembler_Success; }
ret_t rtl8370_getAsicRegBit(uint32 reg, uint32 bitIdx, uint32 *value) { uint16 tmp; if(reg > RTL8370_REGDATAMAX ) return RT_ERR_INPUT; tmp = getReg(reg); tmp = tmp >> bitIdx; tmp &= 1; *value = tmp; return RT_ERR_OK; }
ret_t rtl8370_setAsicRegBit(uint32 reg, uint32 bitIdx, uint32 value) { uint16 tmp; if(reg > RTL8370_REGDATAMAX || value > 1) return RT_ERR_INPUT; tmp = getReg(reg); tmp &= (1 <<bitIdx); tmp |= (value << bitIdx); setReg(reg, tmp); return RT_ERR_OK; }
/* Function Name: * rtl8367b_getAsicReg * Description: * Get content of asic register * Input: * reg - register's address * value - Value setting to register * Output: * None * Return: * RT_ERR_OK - Success * RT_ERR_SMI - SMI access error * Note: * Value 0x0000 will be returned for ASIC un-mapping address */ ret_t rtl8367b_getAsicReg(rtk_uint32 reg, rtk_uint32 *pValue) { #if defined(RTK_X86_ASICDRV) rtk_uint32 regData; ret_t retVal; retVal = Access_Read(reg, 2, ®Data); if(TRUE != retVal) return RT_ERR_SMI; *pValue = regData; if(0x8367B == cleDebuggingDisplay) PRINT("R[0x%4.4x]=0x%4.4x\n", reg, regData); #elif defined(CONFIG_RTL8367B_ASICDRV_TEST) if(reg >= CLE_VIRTUAL_REG_SIZE) return RT_ERR_OUT_OF_RANGE; *pValue = CleVirtualReg[reg]; if(0x8367B == cleDebuggingDisplay) PRINT("R[0x%4.4x]=0x%4.4x\n", reg, CleVirtualReg[reg]); #elif defined(EMBEDDED_SUPPORT) if(reg > RTL8367B_REGDATAMAX ) return RT_ERR_INPUT; *value = getReg(reg); #else rtk_uint32 regData; ret_t retVal; retVal = smi_read(reg, ®Data); if(retVal != RT_ERR_OK) return RT_ERR_SMI; *pValue = regData; #ifdef CONFIG_RTL865X_CLE if(0x8367B == cleDebuggingDisplay) PRINT("R[0x%4.4x]=0x%4.4x\n", reg, regData); #endif #endif return RT_ERR_OK; }
// Reads temperature or threshold // -- whole degrees C only // -- works only with RD_TEMP, ACCESS_TL, and ACCESS_TH int TempSensor::getTemp(byte reg) { int tC; if (reg == RD_TEMP || reg == ACCESS_TL || reg == ACCESS_TH) { byte tVal = getReg(reg); if (tVal >= B10000000) { // negative? tC = 0xFF00 | tVal; // extend sign bits } else { tC = tVal; } return tC; // return threshold } return 0; // bad reg, return 0 }
int DS1621::getTemp(uint8_t reg) { if (reg == RD_TEMP || reg == ACCESS_TL || reg == ACCESS_TH) { int tC; uint8_t tVal = getReg(reg); if (tVal >= B10000000) { // negative? tC = 0xFFFFFF00 | tVal; // extend sign bits } else { tC = tVal; } return tC; // return threshold } return 0; // bad reg, return 0 }
static DecodeStatus DecodeCachePref(MCInst *Inst, unsigned Insn, uint64_t Address, MCRegisterInfo *Decoder) { int Offset = SignExtend32(Insn & 0xffff, 16); unsigned Hint = fieldFromInstruction(Insn, 16, 5); unsigned Base = fieldFromInstruction(Insn, 21, 5); Base = getReg(Decoder, Mips_GPR32RegClassID, Base); MCOperand_CreateReg0(Inst, Base); MCOperand_CreateImm0(Inst, Offset); MCOperand_CreateImm0(Inst, Hint); return MCDisassembler_Success; }
/** * gets the encoder position value as a 32 bit integer. * @param Position is the pointer to the variable holding the value. * @return ERR_OK always. */ byte QD3_getPosition (dword *Position) { dword TimerValue=getReg(TMRD0_CNTR); if (TimerValue>=32000) { qd3_position=qd3_position+ (TimerValue-32000); } else { qd3_position =qd3_position-(32000 - TimerValue); } *Position=qd3_position; setReg(TMRD0_CNTR,32000); setRegBits(TMRD0_CTRL,0x8000); /* Run counter */ return ERR_OK; }
Object loadFile(char* fileName) { if ((yyin = fopen(fileName, "r" )) == NULL) { yyrestart(stdin); return makeNull(); } while (1) { setReg(regExp, read()); if (isEOF(getReg(regExp))) break; eval(); } yyrestart(stdin); return makeSymbol("ok"); }
void parseMem(char *arg, char *code) { char *p; int offset; int i = 16; int bitmask = 0x8000; p = arg; sscanf(arg,"%d(",&offset); while(*p && *p != '$') { p++; } getReg(code,p,REG_S); while(bitmask) { if(bitmask & offset) { code[i] = '1'; } i++; bitmask = bitmask/2; } }
void parseArgs(char *arg, int iType,char * code, int curIndex) { char *p; p = arg; while (isspace(*p)) { p++; } if(iType == TYPE_R) { p = getReg(code, p, REG_D); while (isspace(*p)) { p++; } p = getReg(code, p, REG_S); while (isspace(*p)) { p++; } p = getReg(code, p, REG_T); } else if(iType == TYPE_JR) { p = getReg(code, p, REG_S); } else if(iType == TYPE_I) { p = getReg(code, p, REG_S); while (isspace(*p)) { p++; } p = getReg(code, p, REG_T); while (isspace(*p)) { p++; } getImmediate(code, p, curIndex); } else if(iType == TYPE_J) { while (isspace(*p)) { p++; } getImmediate(code, p, -1); } else if(iType == TYPE_LS) { p = getReg(code, p, REG_T); while (isspace(*p)) { p++; } parseMem(p, code); } else { fprintf(stderr, "DiE IDE DIE\n"); exit(1); } }
int allocateRegForOp(Operand* op, FILE* fp){ //在varList中寻找op对应的变量的VarDes VarDes* var = varList; while(var!=NULL){ if(opCmp(var->op, op)==0) break; var = var->next; } //如果op对应的变量第一次被使用 则记录栈中相对于栈底($fp)的位置(偏移量) int isFirstUsed = FALSE; if(var == NULL){ isFirstUsed = TRUE; var = malloc(sizeof(VarDes)); memset(var, 0, sizeof(VarDes)); var->op = op; var->regNo = -1; if(var->op->kind == VAR_OP || var->op->kind == TEM_VAR_OP){ offset += 4; var->offset = offset; } if(var->op->kind != CONST_OP) addVarToList(var); } //如果op对应的变量没有被分配寄存器 则为其分配寄存器 if(var->regNo < 0){ int regNo = getReg(fp); var->regNo = regNo; regList[regNo].var = var; if(var->op->kind == CONST_OP||var->op->kind == ADDR_OP||(isFirstUsed==FALSE && var->offset>=0)){ //不是第一次出现的变量 ldVar(var, fp); } } //每次寄存器中的变量被使用 old字段就会置零 regList[var->regNo].old = 0; return var->regNo; }
/* ===================================================================*/ byte AD1_GetValue16(word *Values) { if (AD1_ModeFlg != IDLE) { /* Is the device in any measure mode? */ MainMeasure(); /* Call A/D converter handler */ } if (!OutFlg) { /* Is measured value(s) available? */ return ERR_NOTAVAIL; /* If no then error */ } *Values++ = (getReg(ADC_ADRSLT0) + 0U) << 1U; /* Store value from result register of device to user buffer */ *Values++ = (getReg(ADC_ADRSLT1) + 0U) << 1U; /* Store value from result register of device to user buffer */ *Values++ = (getReg(ADC_ADRSLT2) + 0U) << 1U; /* Store value from result register of device to user buffer */ *Values++ = (getReg(ADC_ADRSLT3) + 0U) << 1U; /* Store value from result register of device to user buffer */ *Values++ = (getReg(ADC_ADRSLT4) + 0U) << 1U; /* Store value from result register of device to user buffer */ *Values = (getReg(ADC_ADRSLT5) + 0U) << 1U; /* Store value from result register of device to user buffer */ return ERR_OK; /* OK */ }
ret_t rtl8370_getAsicRegBits(uint32 reg, uint32 bits, uint32 *value) { uint32 regData; uint32 bitsShift; if(reg > RTL8370_REGDATAMAX ) return RT_ERR_INPUT; if(bits>= (1UL<<RTL8370_REGBITLENGTH) ) return RT_ERR_INPUT; bitsShift = 0; while(!(bits & (1UL << bitsShift))) { bitsShift++; if(bitsShift >= RTL8370_REGBITLENGTH) return RT_ERR_INPUT; } regData = getReg(reg); *value = (regData & bits) >> bitsShift; return RT_ERR_OK; }
MCOperand_CreateReg0(Inst, Reg); MCOperand_CreateReg0(Inst, Base); MCOperand_CreateImm0(Inst, Offset); return MCDisassembler_Success; } static DecodeStatus DecodeSpecial3LlSc(MCInst *Inst, unsigned Insn, uint64_t Address, MCRegisterInfo *Decoder) { int64_t Offset = SignExtend64((Insn >> 7) & 0x1ff, 9); unsigned Rt = fieldFromInstruction(Insn, 16, 5); unsigned Base = fieldFromInstruction(Insn, 21, 5); Rt = getReg(Decoder, Mips_GPR32RegClassID, Rt); Base = getReg(Decoder, Mips_GPR32RegClassID, Base); if (MCInst_getOpcode(Inst) == Mips_SC_R6 || MCInst_getOpcode(Inst) == Mips_SCD_R6) { MCOperand_CreateReg0(Inst, Rt); } MCOperand_CreateReg0(Inst, Rt); MCOperand_CreateReg0(Inst, Base); MCOperand_CreateImm0(Inst, Offset); return MCDisassembler_Success; } static DecodeStatus DecodeHWRegsRegisterClass(MCInst *Inst,
int codeGenerate(Tnode *root) { int loc,r,r1,r2; int lbl1,lbl2; struct Gsymbol *TEMP; if(root==NULL) return; switch(root->NODETYPE) { case CONTINUE : codeGenerate(root->Ptr1); codeGenerate(root->Ptr2); return; case ITERATIVE : fprintf(fp,"\n*** ITERATION ***\n"); lbl1 = getLabel(); lbl2 = getLabel(); fprintf(fp,"Label%d:\n",lbl1); r = codeGenerate(root ->Ptr1); fprintf(fp,"JZ R%d Label%d\n",r,lbl2); freeReg(); codeGenerate(root ->Ptr2); fprintf(fp,"JMP Label%d\n",lbl1); fprintf(fp,"Label%d:\n",lbl2); return; case CONDITIONAL : fprintf(fp,"\n*** CONDITIONAL ***\n"); r = codeGenerate(root->Ptr1); lbl1 = getLabel(); lbl2 = getLabel(); fprintf(fp,"JZ R%d Label%d\n",r,lbl1); freeReg(); codeGenerate(root->Ptr2); fprintf(fp,"JMP Label%d\n",lbl2); fprintf(fp,"Label%d:\n",lbl1); codeGenerate(root->Ptr3); fprintf(fp,"Label%d:\n",lbl2); return; case RD : fprintf(fp,"\n*** READ ***\n"); loc = Glookup(root->NAME)->LOCATION; r = getReg(); fprintf(fp,"IN R%d\n",r); fprintf(fp,"MOV [%d] R%d\n",loc,r); freeReg(); return -1; case ARRAYRD : fprintf(fp,"\n*** ARRAY READ ***\n"); r = getReg(); fprintf(fp,"IN R%d\n",r); loc = Glookup(root->NAME)->LOCATION; r1 = codeGenerate(root->Ptr1); r2 = getReg(); fprintf(fp,"MOV R%d %d\n",r2,loc); fprintf(fp,"ADD R%d R%d\n",r1,r2); freeReg(); fprintf(fp,"MOV [R%d] R%d\n",r1,r); freeReg(); freeReg(); return -1; case WRIT : fprintf(fp,"\n*** WRITE ***\n"); r = codeGenerate(root->Ptr1); fprintf(fp,"OUT R%d\n",r); freeReg(); return -1; case ASSIGN : fprintf(fp,"\n*** ASSIGNMENT ***\n"); loc = Glookup(root->NAME)->LOCATION; r = codeGenerate(root->Ptr1); fprintf(fp,"MOV [%d] R%d\n",loc,r); freeReg(); return; case GT : r = codeGenerate(root->Ptr1); codeGenerate(root->Ptr2); fprintf(fp,"GT R%d R%d\n",r,r+1); freeReg(); return r; case LT : r = codeGenerate(root->Ptr1); codeGenerate(root->Ptr2); fprintf(fp,"LT R%d R%d\n",r,r+1); freeReg(); return r; case EQ : r = codeGenerate(root->Ptr1); codeGenerate(root->Ptr2); fprintf(fp,"EQ R%d R%d\n",r,r+1); freeReg(); return r; case NE : r = codeGenerate(root->Ptr1); codeGenerate(root->Ptr2); fprintf(fp,"NE R%d R%d\n",r,r+1); freeReg(); return r; case NUM : r=getReg(); fprintf(fp,"MOV R%d %d \n",r,root->VALUE); return r; case ADD : r=codeGenerate(root->Ptr1); r1=codeGenerate(root->Ptr2); fprintf(fp,"ADD R%d R%d\n",r,r1); freeReg(); return r; case SUB : r=codeGenerate(root->Ptr1); r1=codeGenerate(root->Ptr2); fprintf(fp,"SUB R%d R%d\n",r,r1); freeReg(); return r; case MUL : r=codeGenerate(root->Ptr1); r1=codeGenerate(root->Ptr2); fprintf(fp,"MUL R%d R%d\n",r,r1); freeReg(); return r; case DIV : r=codeGenerate(root->Ptr1); r1=codeGenerate(root->Ptr2); fprintf(fp,"DIV R%d R%d\n",r,r1); freeReg(); return r; case IDFR : loc = Glookup(root->NAME)->LOCATION; r=getReg(); fprintf(fp,"MOV R%d [%d]\n",r,loc); return r; case ARRAYIDFR : r = codeGenerate(root->Ptr1); loc = Glookup(root->NAME)->LOCATION; r1 = getReg(); fprintf(fp,"MOV R%d %d\n",r1,loc); fprintf(fp,"ADD R%d R%d\n",r,r1); fprintf(fp,"MOV R%d [R%d]\n",r1,r); freeReg(); return r1; } }
int8_t vmGetReg(uint8_t reg, int16_t* val) { return getReg(reg, val); }
static int eval1(uint8_t a, uint8_t len) { err = ERR_OK; int tos = 0; sp = stack + STACK_SIZE; uint8_t a1 = a + len; while (a < a1) { uint8_t c = get(a++); uint8_t bcGroup = c & (~(MAX_QUICK - 1)); if (bcGroup == LIT_MASK) { int n = c & (MAX_QUICK - 1); push1(tos); tos = n - MAX_QUICK / 2; } else if (bcGroup == REG_MASK) { int n = c & (MAX_QUICK - 1); int val = 0; char b = getReg(n, &val); if (!b) err = ERR_WRONG_REGISTER; push1(tos); tos = val; } else { switch (c) { case LIT: { int s = get16(a); a += 2; push1(tos); tos = s; break; } case REG: { int s = get16(a); a += 2; int val = 0; char b = getReg(s, &val); if (!b) err = ERR_WRONG_REGISTER; push1(tos); tos = val; break; } case COND: { uint8_t n = get(a++); int n1 = tos; tos = pop1(); if (!n1) a += n; break; } case COND1: { uint8_t n = get(a++); a += n + 1; break; } case EQ: tos = tos == pop1(); break; case NEQ: tos = tos != pop1(); break; case LT: tos = pop1() < tos; break; case LE: tos = pop1() <= tos; break; case GT: tos = pop1() > tos; break; case GE: tos = pop1() >= tos; break; case PLUS: tos = pop1() + tos; break; case MINUS: tos = pop1() - tos; break; case MUL: tos = pop1() * tos; break; case DIV: tos = pop1() / tos; break; case NOT: tos = !tos; break; case NEG: tos = -tos; break; case OR: { uint8_t n = get(a++); tos = tos != 0; if (tos) a += n; else tos = pop1(); break; } case AND: { uint8_t n = get(a++); if (!tos) a += n; else tos = pop1(); break; } case NE0: tos = tos != 0; break; case PAR: break; default: err = ERR_UNKNOWN_BYTECODE; return 0; } } if (err != ERR_OK) return 0; } int n = tos; tos = pop1(); if (err != ERR_OK) return 0; if (sp != stack + STACK_SIZE) err = ERR_STACK_BALANCE; return n; }
int main(int argc, char* argv[]) { if (argc < 2) { printf("Usage: %s <program name>\n", argv[0]); exit(0); } filename = argv[1]; FILE* fp = fopen(filename, "rb"); if (fp == 0) error("opening"); ram = (Byte*)malloc(0x10000); memset(ram, 0, 0x10000); if (ram == 0) { fprintf(stderr, "Out of memory\n"); exit(1); } if (fseek(fp, 0, SEEK_END) != 0) error("seeking"); length = ftell(fp); if (length == -1) error("telling"); if (fseek(fp, 0, SEEK_SET) != 0) error("seeking"); if (length > 0x10000 - 0x100) { fprintf(stderr, "%s is too long to be a .com file\n", filename); exit(1); } if (fread(&ram[0x100], length, 1, fp) != 1) error("reading"); fclose(fp); Word segment = 0x1000; setAX(0x0000); setCX(0x00FF); setDX(segment); registers[3] = 0x0000; setSP(0xFFFE); registers[5] = 0x091C; setSI(0x0100); setDI(0xFFFE); for (int i = 0; i < 4; ++i) registers[8 + i] = segment; Byte* byteData = (Byte*)®isters[0]; int bigEndian = (byteData[2] == 0 ? 1 : 0); int byteNumbers[8] = {0, 2, 4, 6, 1, 3, 5, 7}; for (int i = 0 ; i < 8; ++i) byteRegisters[i] = &byteData[byteNumbers[i] ^ bigEndian]; bool prefix = false; for (int i = 0; i < 1000000000; ++i) { if (!repeating) { if (!prefix) { segmentOverride = -1; rep = 0; } prefix = false; opcode = fetchByte(); } wordSize = ((opcode & 1) != 0); bool sourceIsRM = ((opcode & 2) != 0); int operation = (opcode >> 3) & 7; bool jump; switch (opcode) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x10: case 0x11: case 0x12: case 0x13: case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x20: case 0x21: case 0x22: case 0x23: case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x30: case 0x31: case 0x32: case 0x33: case 0x38: case 0x39: case 0x3a: case 0x3b: // alu rmv,rmv data = readEA(); if (!sourceIsRM) { destination = data; source = getReg(); } else { destination = getReg(); source = data; } aluOperation = operation; doALUOperation(); if (aluOperation != 7) { if (!sourceIsRM) finishWriteEA(data); else setReg(data); } break; case 0x04: case 0x05: case 0x0c: case 0x0d: case 0x14: case 0x15: case 0x1c: case 0x1d: case 0x24: case 0x25: case 0x2c: case 0x2d: case 0x34: case 0x35: case 0x3c: case 0x3d: // alu accum,i destination = getAccum(); source = !wordSize ? fetchByte() : fetchWord(); aluOperation = operation; doALUOperation(); if (aluOperation != 7) setAccum(); break; case 0x06: case 0x0e: case 0x16: case 0x1e: // PUSH segreg push(registers[operation + 8]); break; case 0x07: case 0x17: case 0x1f: // POP segreg registers[operation + 8] = pop(); break; case 0x26: case 0x2e: case 0x36: case 0x3e: // segment override segmentOverride = operation; prefix = true; break; case 0x27: case 0x2f: // DA if (af() || (al() & 0x0f) > 9) { data = al() + (opcode == 0x27 ? 6 : -6); setAL(data); setAF(true); if ((data & 0x100) != 0) setCF(true); } setCF(cf() || al() > 0x9f); if (cf()) setAL(al() + (opcode == 0x27 ? 0x60 : -0x60)); wordSize = false; data = al(); setPZS(); break; case 0x37: case 0x3f: // AA if (af() || (al() & 0xf) > 9) { setAL(al() + (opcode == 0x37 ? 6 : -6)); setAH(ah() + (opcode == 0x37 ? 1 : -1)); setCA(); } else clearCA(); setAL(al() & 0x0f); break; case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: // incdec rw destination = rw(); wordSize = true; setRW(incdec((opcode & 8) != 0)); break; case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57: // PUSH rw push(rw()); break; case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d: case 0x5e: case 0x5f: // POP rw setRW(pop()); break; case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f: case 0xc0: case 0xc1: case 0xc8: case 0xc9: // invalid case 0xcc: case 0xf0: case 0xf1: case 0xf4: // INT 3, LOCK, HLT case 0x9b: case 0xce: case 0x0f: // WAIT, INTO, POP CS case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: // escape case 0xe4: case 0xe5: case 0xe6: case 0xe7: case 0xec: case 0xed: case 0xee: case 0xef: // IN, OUT fprintf(stderr, "Invalid opcode %02x", opcode); runtimeError(""); break; case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f: // Jcond cb switch (opcode & 0x0e) { case 0x00: jump = of(); break; case 0x02: jump = cf(); break; case 0x04: jump = zf(); break; case 0x06: jump = cf() || zf(); break; case 0x08: jump = sf(); break; case 0x0a: jump = pf(); break; case 0x0c: jump = sf() != of(); break; default: jump = sf() != of() || zf(); break; } jumpShort(fetchByte(), jump == ((opcode & 1) == 0)); break; case 0x80: case 0x81: case 0x82: case 0x83: // alu rmv,iv destination = readEA(); data = fetch(opcode == 0x81); if (opcode != 0x83) source = data; else source = signExtend(data); aluOperation = modRMReg(); doALUOperation(); if (aluOperation != 7) finishWriteEA(data); break; case 0x84: case 0x85: // TEST rmv,rv data = readEA(); test(data, getReg()); break; case 0x86: case 0x87: // XCHG rmv,rv data = readEA(); finishWriteEA(getReg()); setReg(data); break; case 0x88: case 0x89: // MOV rmv,rv ea(); finishWriteEA(getReg()); break; case 0x8a: case 0x8b: // MOV rv,rmv setReg(readEA()); break; case 0x8c: // MOV rmw,segreg ea(); wordSize = 1; finishWriteEA(registers[modRMReg() + 8]); break; case 0x8d: // LEA address = ea(); if (!useMemory) runtimeError("LEA needs a memory address"); setReg(address); break; case 0x8e: // MOV segreg,rmw wordSize = 1; data = readEA(); registers[modRMReg() + 8] = data; break; case 0x8f: // POP rmw writeEA(pop()); break; case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: // XCHG AX,rw data = ax(); setAX(rw()); setRW(data); break; case 0x98: // CBW setAX(signExtend(al())); break; case 0x99: // CWD setDX((ax() & 0x8000) == 0 ? 0x0000 : 0xffff); break; case 0x9a: // CALL cp savedIP = fetchWord(); savedCS = fetchWord(); farCall(); break; case 0x9c: // PUSHF push((flags & 0x0fd7) | 0xf000); break; case 0x9d: // POPF flags = pop() | 2; break; case 0x9e: // SAHF flags = (flags & 0xff02) | ah(); break; case 0x9f: // LAHF setAH(flags & 0xd7); break; case 0xa0: case 0xa1: // MOV accum,xv data = read(fetchWord()); setAccum(); break; case 0xa2: case 0xa3: // MOV xv,accum write(getAccum(), fetchWord()); break; case 0xa4: case 0xa5: // MOVSv stoS(lodS()); doRep(); break; case 0xa6: case 0xa7: // CMPSv lodDIS(); source = data; sub(); doRep(); break; case 0xa8: case 0xa9: // TEST accum,iv data = fetch(wordSize); test(getAccum(), data); break; case 0xaa: case 0xab: // STOSv stoS(getAccum()); doRep(); break; case 0xac: case 0xad: // LODSv data = lodS(); setAccum(); doRep(); break; case 0xae: case 0xaf: // SCASv lodDIS(); destination = getAccum(); source = data; sub(); doRep(); break; case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: setRB(fetchByte()); break; case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf: // MOV rv,iv setRW(fetchWord()); break; case 0xc2: case 0xc3: case 0xca: case 0xcb: // RET savedIP = pop(); savedCS = (opcode & 8) == 0 ? cs() : pop(); if (!wordSize) setSP(sp() + fetchWord()); farJump(); break; case 0xc4: case 0xc5: // LES/LDS ea(); farLoad(); *modRMRW() = savedIP; registers[8 + (!wordSize ? 0 : 3)] = savedCS; break; case 0xc6: case 0xc7: // MOV rmv,iv ea(); finishWriteEA(fetch(wordSize)); break; case 0xcd: data = fetchByte(); if (data != 0x21) { fprintf(stderr, "Unknown interrupt 0x%02x", data); runtimeError(""); } switch (ah()) { case 2: printf("%c", dl()); break; case 0x4c: printf("*** Bytes: %i\n", length); printf("*** Cycles: %i\n", ios); printf("*** EXIT code %i\n", al()); exit(0); break; default: fprintf(stderr, "Unknown DOS call 0x%02x", data); runtimeError(""); } break; case 0xcf: ip = pop(); setCS(pop()); flags = pop() | 2; break; case 0xd0: case 0xd1: case 0xd2: case 0xd3: // rot rmv,n data = readEA(); if ((opcode & 2) == 0) source = 1; else source = cl(); while (source != 0) { destination = data; switch (modRMReg()) { case 0: // ROL data <<= 1; doCF(); data |= (cf() ? 1 : 0); setOFRotate(); break; case 1: // ROR setCF((data & 1) != 0); data >>= 1; if (cf()) data |= (!wordSize ? 0x80 : 0x8000); setOFRotate(); break; case 2: // RCL data = (data << 1) | (cf() ? 1 : 0); doCF(); setOFRotate(); break; case 3: // RCR data >>= 1; if (cf()) data |= (!wordSize ? 0x80 : 0x8000); setCF((destination & 1) != 0); setOFRotate(); break; case 4: // SHL case 6: data <<= 1; doCF(); setOFRotate(); setPZS(); break; case 5: // SHR setCF((data & 1) != 0); data >>= 1; setOFRotate(); setAF(true); setPZS(); break; case 7: // SAR setCF((data & 1) != 0); data >>= 1; if (!wordSize) data |= (destination & 0x80); else data |= (destination & 0x8000); setOFRotate(); setAF(true); setPZS(); break; } --source; } finishWriteEA(data); break; case 0xd4: // AAM data = fetchByte(); if (data == 0) divideOverflow(); setAH(al() / data); setAL(al() % data); wordSize = true; setPZS(); break; case 0xd5: // AAD data = fetchByte(); setAL(al() + ah()*data); setAH(0); setPZS(); break; case 0xd6: // SALC setAL(cf() ? 0xff : 0x00); break; case 0xd7: // XLATB setAL(readByte(bx() + al())); break; case 0xe0: case 0xe1: case 0xe2: // LOOPc cb setCX(cx() - 1); jump = (cx() != 0); switch (opcode) { case 0xe0: if (zf()) jump = false; break; case 0xe1: if (!zf()) jump = false; break; } jumpShort(fetchByte(), jump); break; case 0xe3: // JCXZ cb jumpShort(fetchByte(), cx() == 0); break; case 0xe8: // CALL cw call(ip + fetchWord()); break; case 0xe9: // JMP cw ip += fetchWord(); break; case 0xea: // JMP cp savedIP = fetchWord(); savedCS = fetchWord(); farJump(); break; case 0xeb: // JMP cb jumpShort(fetchByte(), true); break; case 0xf2: case 0xf3: // REP rep = opcode == 0xf2 ? 1 : 2; prefix = true; break; case 0xf5: // CMC flags ^= 1; break; case 0xf6: case 0xf7: // math rmv data = readEA(); switch (modRMReg()) { case 0: case 1: // TEST rmv,iv test(data, fetch(wordSize)); break; case 2: // NOT iv finishWriteEA(~data); break; case 3: // NEG iv source = data; destination = 0; sub(); finishWriteEA(data); break; case 4: case 5: // MUL rmv, IMUL rmv source = data; destination = getAccum(); data = destination; setSF(); setPF(); data *= source; setAX(data); if (!wordSize) { if (modRMReg() == 4) setCF(ah() != 0); else { if ((source & 0x80) != 0) setAH(ah() - destination); if ((destination & 0x80) != 0) setAH(ah() - source); setCF(ah() == ((al() & 0x80) == 0 ? 0 : 0xff)); } } else { setDX(data >> 16); if (modRMReg() == 4) { data |= dx(); setCF(dx() != 0); } else { if ((source & 0x8000) != 0) setDX(dx() - destination); if ((destination & 0x8000) != 0) setDX(dx() - source); data |= dx(); setCF(dx() == ((ax() & 0x8000) == 0 ? 0 : 0xffff)); } } setZF(); setOF(cf()); break; case 6: case 7: // DIV rmv, IDIV rmv source = data; if (source == 0) divideOverflow(); if (!wordSize) { destination = ax(); if (modRMReg() == 6) { div(); if (data > 0xff) divideOverflow(); } else { destination = ax(); if ((destination & 0x8000) != 0) destination |= 0xffff0000; source = signExtend(source); div(); if (data > 0x7f && data < 0xffffff80) divideOverflow(); } setAH(remainder); setAL(data); } else { destination = (dx() << 16) + ax(); div(); if (modRMReg() == 6) { if (data > 0xffff) divideOverflow(); } else { if (data > 0x7fff && data < 0xffff8000) divideOverflow(); } setDX(remainder); setAX(data); } break; } break; case 0xf8: case 0xf9: // STC/CLC setCF(wordSize); break; case 0xfa: case 0xfb: // STI/CLI setIF(wordSize); break; case 0xfc: case 0xfd: // STD/CLD setDF(wordSize); break; case 0xfe: case 0xff: // misc ea(); if ((!wordSize && modRMReg() >= 2 && modRMReg() <= 6) || modRMReg() == 7) { fprintf(stderr, "Invalid instruction %02x %02x", opcode, modRM); runtimeError(""); } switch (modRMReg()) { case 0: case 1: // incdec rmv destination = readEA2(); finishWriteEA(incdec(modRMReg() != 0)); break; case 2: // CALL rmv call(readEA2()); break; case 3: // CALL mp farLoad(); farCall(); break; case 4: // JMP rmw ip = readEA2(); break; case 5: // JMP mp farLoad(); farJump(); break; case 6: // PUSH rmw push(readEA2()); break; } break; } } runtimeError("Timed out"); }