void cgLdContResumeAddr(IRLS& env, const IRInstruction* inst) { auto const dst = dstLoc(env, inst, 0).reg(); auto const cont = srcLoc(env, inst, 0).reg(); auto const isAsync = inst->extra<IsAsyncData>()->isAsync; auto const addrOff = BaseGenerator::resumeAddrOff() - genOffset(isAsync); vmain(env) << load{cont[addrOff], dst}; }
void cgContPreNext(IRLS& env, const IRInstruction* inst) { auto const cont = srcLoc(env, inst, 0).reg(); auto const checkStarted = inst->src(1)->boolVal(); auto const isAsync = inst->extra<IsAsyncData>()->isAsync; auto& v = vmain(env); auto const sf = v.makeReg(); // These asserts make sure that the startedCheck work. static_assert(uint8_t(BaseGenerator::State::Created) == 0, "used below"); static_assert(uint8_t(BaseGenerator::State::Started) == 1, "used below"); static_assert(uint8_t(BaseGenerator::State::Done) > 3, ""); // These asserts ensure that the state transition works. If we're in the // Created state we want to transition to Priming, and if we're in the // Started state we want to transition to Running. By laying out the enum // this way we can avoid the branch and just transition by adding 2 to the // current state. static_assert(uint8_t(BaseGenerator::State::Priming) == uint8_t(BaseGenerator::State::Created) + 2, "used below"); static_assert(uint8_t(BaseGenerator::State::Running) == uint8_t(BaseGenerator::State::Started) + 2, "used below"); // Take exit if state != 1 (checkStarted) or if state > 1 (!checkStarted). auto stateOff = BaseGenerator::stateOff() - genOffset(isAsync); v << cmpbim{int8_t(BaseGenerator::State::Started), cont[stateOff], sf}; fwdJcc(v, env, checkStarted ? CC_NE : CC_A, sf, inst->taken()); // Transition the generator into either the Priming state (if we were just // created) or the Running state (if we were started). Due to the way the // enum is layed out, we can model this by just adding 2. v << addlim{int8_t(2), cont[stateOff], v.makeReg()}; }
void cgContValid(IRLS& env, const IRInstruction* inst) { auto const dst = dstLoc(env, inst, 0).reg(); auto const cont = srcLoc(env, inst, 0).reg(); auto const isAsync = inst->extra<IsAsyncData>()->isAsync; auto& v = vmain(env); // Return true if generator state is not Done. auto const sf = v.makeReg(); auto const stateOff = BaseGenerator::stateOff() - genOffset(isAsync); v << cmpbim{int8_t(BaseGenerator::State::Done), cont[stateOff], sf}; v << setcc{CC_NE, sf, dst}; }
void cgContStarted(IRLS& env, const IRInstruction* inst) { auto const dst = dstLoc(env, inst, 0).reg(); auto const cont = srcLoc(env, inst, 0).reg(); auto& v = vmain(env); // Return true if generator state is not in the Created state. auto const sf = v.makeReg(); auto const stateOff = BaseGenerator::stateOff() - genOffset(false /* isAsync */); v << cmpbim{int8_t(BaseGenerator::State::Created), cont[stateOff], sf}; v << setcc{CC_NE, sf, dst}; }
void cgContStartedCheck(IRLS& env, const IRInstruction* inst) { auto const cont = srcLoc(env, inst, 0).reg(); auto const isAsync = inst->extra<IsAsyncData>()->isAsync; auto& v = vmain(env); static_assert(uint8_t(BaseGenerator::State::Created) == 0, "used below"); // Take exit if state == 0. auto const sf = v.makeReg(); auto const stateOff = BaseGenerator::stateOff() - genOffset(isAsync); v << testbim{int8_t(0xffu), cont[stateOff], sf}; v << jcc{CC_Z, sf, {label(env, inst->next()), label(env, inst->taken())}}; }
/*Writes coresponing code to file, or throws appropriate error */ void processOpcode( int code, int * steer, char * pArg1, char * pArg2, char * pArg3, char * pArg4) { int output = 0; int DR = -1; int SR = -1; int SR1 = -1; int SR2 = -1; int BR = -1; int num = -1; Symbol* temp = NULL; if(code <= 15 && code >= 0) output = code<<12; switch (code) { case 0: /* BR if steering is 1-7 and NOP if 0 */ if(*pArg2 != '\0' || *pArg3 != '\0' || *pArg4 !='\0'){ printf("Error: invalid argument\n"); closeFiles(); exit(4); } if(*steer==0 && *pArg1 != '\0') { printf("Error: invalid argument\n"); closeFiles(); exit(4); } if(*steer != 0) { /* br with nzp bits specified by steering */ output += *steer<<9; temp = searchSymbol(pArg1); if(temp == NULL) /*Label not found in symbol tabel */ { printf("Error: Unidentified Label\n"); closeFiles(); exit(1); } num = genOffset(temp->location,9); /*genOffset will throw out of bounds error if necisarry */ output += (num&511); } break; case 1: /*ADD */ DR = RegNum(pArg1); SR1 = RegNum(pArg2); /*Too many arguments, or invalid */ if(*pArg4 != '\0'||SR1 == -1 || DR == -1) { printf("Error: invalid argument\n"); closeFiles(); exit(4); } output += (DR<<9)+(SR1<<6); /*Common to all implementations */ SR2=RegNum(pArg3); if(SR2 == -1) /*Immediate Value */ { num = toNum(pArg3); if(num>15 || num < -16) /*5 Bits */ { printf("Error: Immediate Value Out of Bounds\n"); closeFiles(); exit(3); } output+= (1<<5) + (num&31); } else /*Register value */ { output+=SR2; } break; case 2: /*LDB*/ DR = RegNum(pArg1); BR = RegNum(pArg2); if(*pArg4 != '\0'|| BR == -1 || DR == -1) { printf("Error: invalid argument\n"); closeFiles(); exit(4); } output += (DR<<9)+(BR<<6); num = toNum(pArg3); if(num>31 || num < -32) /* 6 Bits */ { printf("Error: Immediate Value Out of Bounds\n"); closeFiles(); exit(3); } output += (num&63); break; case 3: /*STB*/ SR = RegNum(pArg1); BR = RegNum(pArg2); if(*pArg4 != '\0'|| BR == -1 || SR == -1) { printf("Error: invalid argument\n"); closeFiles(); exit(4); } output += (SR<<9)+(BR<<6); num = toNum(pArg3); if(num>31 || num < -32) /* 6 Bits */ { printf("Error: Immediate Value Out of Bounds\n"); closeFiles(); exit(3); } output += (num&63); break; case 4: /* JSR & JSRR */ if(*pArg2 != '\0' || *pArg3 != '\0' || *pArg4 != '\0') { printf("Error: invalid argument\n"); closeFiles(); exit(4); } output += *steer << 11; if(*steer == 1) { /* JSR */ temp = searchSymbol(pArg1); if(temp == NULL) { /*Label not found in symbol tabel */ printf("Error: Unidentified Label\n"); closeFiles(); exit(1); } num = genOffset(temp->location,11); /*genOffset will throw out of bounds error if necisarry */ output += (num&2047); } else { /* JSRR */ BR = RegNum(pArg1); output += BR<<6; } break; case 5: /*AND */ DR = RegNum(pArg1); SR1 = RegNum(pArg2); /*Too many arguments, or invalid */ if(*pArg4 != '\0'||SR1 == -1 || DR == -1) { printf("Error: invalid argument\n"); closeFiles(); exit(4); } output += (DR<<9)+(SR1<<6); /*Common to all implementations */ SR2=RegNum(pArg3); if(SR2 == -1) /*Immediate Value */ { num = toNum(pArg3); if(num>15 || num < -16) /*5 Bits */ { printf("Error: Immediate Value Out of Bounds\n"); closeFiles(); exit(3); } output+= (1<<5) + (num & 31); } else /*Register value */ { output+=SR2; } break; case 6: /*LDW*/ DR = RegNum(pArg1); BR = RegNum(pArg2); if(*pArg4 != '\0'|| BR == -1 || DR == -1) { printf("Error: invalid argument\n"); closeFiles(); exit(4); } output += (DR<<9)+(BR<<6); num = toNum(pArg3); if(num>31 || num < -32) /* 6 Bits */ { printf("Error: Immediate Value Out of Bounds\n"); closeFiles(); exit(3); } output += (num&63); break; case 7: /*STW*/ SR = RegNum(pArg1); BR = RegNum(pArg2); if(*pArg4 != '\0'|| BR == -1 || SR == -1) { printf("Error: invalid argument\n"); closeFiles(); exit(4); } output += (SR<<9)+(BR<<6); num = toNum(pArg3); if(num>31 || num < -32) /* 6 Bits */ { printf("Error: Immediate Value Out of Bounds\n"); closeFiles(); exit(3); } output += (num&63); break; case 8: /* RTI */ /* do nothing: bits 11-0 all 0 */ break; case 9: /*XOR and NOT */ DR = RegNum(pArg1); SR1 = RegNum(pArg2); /*Too many arguments, or invalid */ if(*pArg4 != '\0'||SR1 == -1 || DR == -1) { printf("Error: invalid argument\n"); closeFiles(); exit(4); } output += (DR<<9)+(SR1<<6); /*Common to all implementations */ if(*steer == 0) /*XOR*/ { SR2=RegNum(pArg3); if(SR2 == -1) /*Immediate Value */ { num = toNum(pArg3); if(num>15 || num < -16) /*5 Bits */ { printf("Error: Immediate Value Out of Bounds\n"); closeFiles(); exit(3); } output+= (1<<5) + (num&31); } else /*Register value */ { output+=SR2; } } else /*NOT function */ { if(*pArg3 != '\0') { printf("Error: invalid argument\n"); closeFiles(); exit(4); } output += 63; } break; /*Opcodes 10 and 11 are invalid */ case 12: /*JMP */ if(*pArg2 != '\0' ||*pArg3 != '\0' || *pArg4 != '\0') { printf("Error: invalid argument\n"); closeFiles(); exit(4); } if(*steer == 0) { SR1 = RegNum(pArg1); if(SR1==-1) /*Must be valid register */ { printf("Error: invalid argument\n"); closeFiles(); exit(4); } output+=SR1<<6; } else /*RET */ { if(*pArg1 != '\0') /*Should not have anything here */ { printf("Error: invalid argument\n"); closeFiles(); exit(4); } output+=7<<6; } break; case 13: /*Shift */ DR = RegNum(pArg1); SR1 = RegNum(pArg2); num = toNum(pArg3); if(*pArg4 != '\0' || DR==-1||SR1==-1) { printf("Error: invalid argument\n"); closeFiles(); exit(4); } if(num>15||num<0) { printf("Error: Immediate Value Out of Bounds\n"); closeFiles(); exit(3); } /*Steering integer also acts as steering bits */ output += (DR<<9)+(SR1<<6)+((*steer)<<4)+num; break; case 14: /*LEA */ DR = RegNum(pArg1); temp = searchSymbol(pArg2); if(temp == NULL) /*Label not found in symbol tabel */ { printf("Error: Unidentified Label\n"); closeFiles(); exit(1); } if(DR==-1 || *pArg3 != '\0' || *pArg4 != '\0') { printf("Error: invalid argument\n"); closeFiles(); exit(4); } num = genOffset(temp->location,9); /*genOffset will throw out of bounds error if necisarry */ output+=(DR<<9)+(num&511); break; case 15: /*TRAP */ /*Must be hex */ if(*pArg2 != '\0' || *pArg3 != '\0' || *pArg4 != '\0') { printf("Error: invalid argument\n"); closeFiles(); exit(4); } if(*steer == 1) /*HALT */ { if(*pArg1 != '\0') { printf("Error: invalid argument\n"); closeFiles(); exit(4); } num= 37; } else { if(*pArg1 != 'x') /*Must be a hex value */ { printf("Error: TRAP must be a hex value\n"); closeFiles(); exit(3); } num = toNum(pArg1); if(num>255||num<0) /*>0 and no more than 8 digits */ { printf("Error: TRAP Value Out of Bounds\n"); closeFiles(); exit(3); } } output+=num; break; case 16: /*.FILL */ if(*pArg2 != '\0' || *pArg3 != '\0' || *pArg4 != '\0') { printf("Error: invalid argument\n"); closeFiles(); exit(4); } num = toNum(pArg1); if(num>65535|| num< -32768) /*Can be signed or unsigned */ { printf("Error: TRAP Value Out of Bounds\n"); closeFiles(); exit(3); } output = num; break; default: printf("Error: invalid opcode\n"); closeFiles(); exit(2); } fprintf( outfile, "0x%0.4X\n", output ); /*Prints out formated Hex version of code */ }