/* XMODEM termination processing */ LOCAL void xmodemEnd(W er) { // finish XMODEM protocol while (er >= 0) er = xmodemRead(); if (er != E_END && er != E_CANCEL) { purgeInput(); // wait until there is no more data outputByte(CAN); // transmite two (or more) consecutive CANs outputByte(CAN); outputByte(CAN); } }
int handleStateChange(BFState * interp,char command){ switch(command){ case '>': incrementDataPointer(interp); break; case '<': decrementDataPointer(interp); break; case '+': incrementCurrentByte(interp); break; case '-': decrementCurrentByte(interp); break; case '.': outputByte(interp); break; case ',': inputByte(interp); break; case '[': case ']': return 1; default: return 2; } return 0; }
void outputAlignedDataList(FILE *f, int size, AST *ast) { if (size > 1) { while ((datacount % size) != 0) { outputByte(f, 0); } } outputDataList(f, size, ast); }
void outputDataList(FILE *f, int size, AST *ast) { unsigned val, origval; int i, reps; AST *sub; while (ast) { sub = ast->left; if (sub->kind == AST_ARRAYDECL || sub->kind == AST_ARRAYREF) { origval = EvalPasmExpr(ast->left->left); reps = EvalPasmExpr(ast->left->right); } else if (sub->kind == AST_STRING) { const char *ptr = sub->d.string; while (*ptr) { val = (*ptr++) & 0xff; outputByte(f, val); for (i = 1; i < size; i++) { outputByte(f, 0); } } reps = 0; } else { origval = EvalPasmExpr(ast->left); reps = 1; } while (reps > 0) { val = origval; for (i = 0; i < size; i++) { outputByte(f, val & 0xff); val = val >> 8; } --reps; } ast = ast->right; } }
/* * output bytes for a file */ static void assembleFile(FILE *f, AST *ast) { FILE *inf; const char *name = ast->d.string; int c; inf = fopen(name, "rb"); if (!inf) { ERROR(ast, "file %s: %s", name, strerror(errno)); return; } while ((c = fgetc(inf)) >= 0) { outputByte(f, c); } fclose(inf); }
void assembleInstruction(FILE *f, AST *ast) { uint32_t val, mask, src, dst; Instruction *instr; int i, numoperands, expectops; AST *operand[MAX_OPERANDS]; AST *line = ast; char *callname; AST *retast; instr = (Instruction *)ast->d.ptr; val = instr->binary; if (instr->ops != NOP_OPERANDS) { /* for anything except NOP set the condition to "always" */ val |= 0xf << 18; } /* check for modifiers and operands */ numoperands = 0; ast = ast->right; while (ast != NULL) { if (ast->kind == AST_EXPRLIST) { if (numoperands >= MAX_OPERANDS) { ERROR(line, "Too many operands to instruction"); return; } operand[numoperands++] = ast->left; } else if (ast->kind == AST_INSTRMODIFIER) { InstrModifier *mod = (InstrModifier *)ast->d.ptr; mask = mod->modifier; if (mask & 0x80000000) { val = val & mask; } else { val = val | mask; } } else { ERROR(line, "Internal error: expected instruction modifier found %d", ast->kind); return; } ast = ast->right; } /* parse operands and put them in place */ switch (instr->ops) { case NO_OPERANDS: case NOP_OPERANDS: expectops = 0; break; case TWO_OPERANDS: case JMPRET_OPERANDS: expectops = 2; break; default: expectops = 1; break; } if (expectops != numoperands) { ERROR(line, "Expected %d operands for %s, found %d", expectops, instr->name, numoperands); return; } src = dst = 0; switch (instr->ops) { case NO_OPERANDS: case NOP_OPERANDS: break; case TWO_OPERANDS: case JMPRET_OPERANDS: dst = EvalPasmExpr(operand[0]); src = EvalPasmExpr(operand[1]); break; case SRC_OPERAND_ONLY: dst = 0; src = EvalPasmExpr(operand[0]); break; case DST_OPERAND_ONLY: dst = EvalPasmExpr(operand[0]); src = 0; break; case CALL_OPERAND: if (operand[0]->kind != AST_IDENTIFIER) { ERROR(operand[0], "call operand must be an identifier"); return; } src = EvalPasmExpr(operand[0]); callname = malloc(strlen(operand[0]->d.string) + 8); strcpy(callname, operand[0]->d.string); strcat(callname, "_ret"); retast = NewAST(AST_IDENTIFIER, NULL, NULL); retast->d.string = callname; dst = EvalPasmExpr(retast); break; default: ERROR(line, "Unsupported instruction `%s'", instr->name); return; } if (src > 511) { ERROR(line, "Source operand too big for %s", instr->name); return; } if (dst > 511) { ERROR(line, "Destination operand too big for %s", instr->name); return; } val = val | (dst << 9) | src; /* output the instruction */ /* make sure it is aligned */ while ((datacount % 4) != 0) { outputByte(f, 0); } for (i = 0; i < 4; i++) { outputByte(f, val & 0xff); val = val >> 8; } }
/* XMODEM read processing */ LOCAL W xmodemRead(void) { W i, c, ctlch; UB cksum; if (blkptr < blksz) return blkbuf[blkptr++]; c = 0; ctlch = ACK; if (blkno++ == 0) { /* only for the initial packet transfer */ outputByte(NAK); c = inputByte(SOH1_TMO); ctlch = -1; } for (;;) { // receiving block for (i = 0;;) { if (ctlch >= 0) { // ack/beginning character is transmitted outputByte(ctlch); // leading letter in the ack is extracted c = inputByte(SOH_TMO); } ctlch = NAK; if (c == SOH) {blksz = BLK_SZ; break;} if (c == STX) {blksz = XBLK_SZ; break;} if (c == CAN || c == CTLC) { // cancel transfer // Is CAN followed by another CAN? c = inputByte(IDLE_TMO); if (c < 0 || c == CAN || c == CTLC) return E_CANCEL; } else if (c == EOT) { // end of transmission outputByte(ACK); return E_END; } purgeInput(); // skip data if (++i >= MAX_RETRY) return E_XMODEM; } // read a block number & check if ((i = inputByte(RECV_TMO)) < 0) continue; if ((c = inputByte(RECV_TMO)) < 0) continue; if (i + c != 0xff) continue; if (i != (blkno & 0xff)) { if (i != ((blkno - 1) & 0xff)) return E_XMODEM; // skip if the previous block is read ctlch = ACK; } // read the block itself for (cksum = 0, i = 0; i < blksz; i++) { if ((c = inputByte(RECV_TMO)) < 0) break; cksum += (blkbuf[i] = c); } if (c < 0) continue; // validate checksum if (inputByte(RECV_TMO) == cksum && ctlch != ACK) break; } blkptr = 0; return blkbuf[blkptr++]; }