void SAM(C64 *the_c64) { bool done = false; char c; TheCPU = the_c64->TheCPU; TheCPU1541 = the_c64->TheCPU1541; TheVIC = the_c64->TheVIC; TheSID = the_c64->TheSID; TheCIA1 = the_c64->TheCIA1; TheCIA2 = the_c64->TheCIA2; // Get CPU registers and current memory configuration TheCPU->GetState(&R64); TheCPU->ExtConfig = (~R64.ddr | R64.pr) & 7; TheCPU1541->GetState(&R1541); #ifdef __riscos__ Wimp_CommandWindow((int)"SAM"); #endif #ifdef AMIGA if (!(fin = fout = ferr = fopen("CON:0/0/640/480/SAM", "w+"))) return; #else fin = stdin; fout = stdout; ferr = stdout; #endif access_1541 = false; address = R64.pc; fprintf(ferr, "\n *** SAM - Simple Assembler and Monitor ***\n *** Press 'h' for help ***\n\n"); init_abort(); display_registers(); while (!done) { if (access_1541) fprintf(ferr, "1541> "); else fprintf(ferr, "C64> "); fflush(ferr); read_line(); while ((c = get_char()) == ' ') ; switch (c) { case 'a': // Assemble get_token(); assemble(); break; case 'b': // Binary dump get_token(); binary_dump(); break; case 'c': // Compare get_token(); compare(); break; case 'd': // Disassemble get_token(); disassemble(); break; case 'e': // Interrupt vectors int_vectors(); break; case 'f': // Fill get_token(); fill(); break; case 'h': // Help help(); break; case 'i': // ASCII dump get_token(); ascii_dump(); break; case 'k': // Memory configuration get_token(); mem_config(); break; case 'l': // Load data get_token(); load_data(); break; case 'm': // Memory dump get_token(); memory_dump(); break; case 'n': // Screen code dump get_token(); screen_dump(); break; case 'o': // Redirect output get_token(); redir_output(); break; case 'p': // Sprite dump get_token(); sprite_dump(); break; case 'r': // Registers get_reg_token(); registers(); break; case 's': // Save data get_token(); save_data(); break; case 't': // Transfer get_token(); transfer(); break; case 'v': // View machine state view_state(); break; case 'x': // Exit done = true; break; case ':': // Change memory get_token(); modify(); break; case '1': // Switch to 1541 mode access_1541 = true; break; case '6': // Switch to C64 mode access_1541 = false; break; case '?': // Compute expression get_token(); print_expr(); break; case '\n': // Blank line break; default: // Unknown command error("Unknown command"); break; } } exit_abort(); #ifdef AMIGA fclose(fin); #endif if (fout != ferr) fclose(fout); #ifdef __riscos__ Wimp_CommandWindow(-1); #endif // Set CPU registers TheCPU->SetState(&R64); TheCPU1541->SetState(&R1541); }
static int masm_main_loop(char * obj_file,char * src_file) { FILE * obj_fp, *src_fp; char buf[BUFSIZ] = {0}; int length; char * p, * q; src_fp = obj_fp = NULL; uint32_t counter = 0; uint32_t lines = 0; hash_table * label_hash = hash_create(512); char op_name[128]; char label[128]; char rd[6]; char rs[6]; char rt[6]; char imm[20]; int32_t rd_num,rs_num,rt_num,imm_num; if((src_fp = fopen(src_file,"r")) == NULL) { printf("Can not open %s:%s\n",src_file,strerror(errno)); } if((obj_fp = fopen(obj_file,"w+")) == NULL) { printf("Can not open %s:%s\n",obj_file,strerror(errno)); } int total_lines = get_file_lines(src_fp); uint32_t * instruction = calloc(1,total_lines * sizeof(uint32_t)); var_t * var = calloc(1,total_lines * sizeof(var_t)); int var_count = 0; fseek(src_fp,0L,SEEK_SET); while(1) { fgets(buf,BUFSIZ,src_fp); if(feof(src_fp)) { break; } lines++; length = strlen(buf); p = buf; //skip whitespace while(length > 0 &&isspace(p[0])) { length--; p++; } //printf("length=%d\t%s",length,buf+i); if(p[0] == ';' || p[0] == '\0') { continue; } q = get_first_token(p); strncpy(op_name, p , q-p); op_name[q-p] = '\0'; if(line_has_label(p)) { /* it is label */ label_t l; l.name = op_name; l.real_line = lines; l.line = counter; hash_add_item(&label_hash,str2hash(op_name),&l); p = skip_label_wthie(q); /* 获得字符串 */ q = get_opcode_token(p); strncpy(op_name, p , q-p); op_name[q-p] = '\0'; //printf("%s",op_name); } /* p now a opcode start q-p is opecode */ int op_index = verify_opcode(op_name,lines); q = skip_wthie(q); p = q; /* now at rd */ switch(op_index) { #if 1 case ADD: case SUB: case MUL: case DIV: case MOD: case AND: case OR: case NOT: case XOR: case LWORD: case SWORD: /* 获得字符串 */ q = get_reg_token(p); strncpy(rd, p , q-p); rd[q-p] = '\0'; q = skip_reg_wthie(q); p = q; q = get_reg_token(p); strncpy(rs, p , q-p); rs[q-p] = '\0'; q = skip_reg_wthie(q); p = q; q = get_reg_token(p); strncpy(rt, p , q-p); rt[q-p] = '\0'; rd_num = get_reg_index(rd,lines); rs_num = get_reg_index(rs,lines); rt_num = get_reg_index(rt,lines); instruction[counter] = (op_index << 26) | (rd_num << 21) | (rs_num << 16)| (rt_num << 11); break; ///C语言中的左移就是逻辑左移,而右移, ///对于无符号数来说就是逻辑右移, ///对有符号来说就是算术右移 ///想要实现符号左移,比较麻烦一点,首先保存最高位,然后左移之后补上最高位。 case SLL: case SLR: case SAL: case SAR: case ADDI: case ANDI: ///这里的立即数是0扩展的。 case ORI: case XORI: case LUI: ///哦,载入高16位数啊,靠,那么低位怎么载入呢?用ori q = get_reg_token(p); strncpy(rd, p , q-p); rd[q-p] = '\0'; q = skip_reg_wthie(q); p = q; q = get_reg_token(p); strncpy(rs, p , q-p); rs[q-p] = '\0'; q = skip_reg_wthie(q); p = q; q = get_reg_token(p); strncpy(imm, p , q-p); imm[q-p] = '\0'; rd_num = get_reg_index(rd,lines); rs_num = get_reg_index(rs,lines); imm_num = atoi(imm); if(imm_num > 32767 || imm_num < -32768) { printf("________\n"); printf("[ERROR 6] line: %d imm num is too lager or too smaller\n",lines); } instruction[counter] = (op_index << 26) | (rd_num << 21) | (rs_num << 16)| (imm_num & 0x0000ffff); break; case LESS: case GREAT: case LESSE: case GREATE: case LESSU: case GREATU: case LESSEU: case GREATEU: case EQUAL: case UEQUAL: q = get_reg_token(p); strncpy(rd, p , q-p); rd[q-p] = '\0'; q = skip_reg_wthie(q); p = q; q = get_reg_token(p); strncpy(rs, p , q-p); rs[q-p] = '\0'; q = skip_reg_wthie(q); p = q; q = get_reg_token(p); strncpy(label, p , q-p); label[q-p] = '\0'; rd_num = get_reg_index(rd,lines); rs_num = get_reg_index(rs,lines); var[var_count].name = malloc(strlen(label) + 1); strcpy(var[var_count].name, label); var[var_count].line = counter; var_count++; instruction[counter] = (op_index << 26) | (rd_num << 21) | (rs_num << 16) | 0x0; break; case JMP: q = get_reg_token(p); strncpy(label, p , q-p); label[q-p] = '\0'; var[var_count].name = malloc(strlen(label) + 1); strcpy(var[var_count].name, label); var[var_count].line = counter; var_count++; instruction[counter] = (op_index << 26); break; /* 存储指令 */ case MOV: q = get_reg_token(p); strncpy(rd, p , q-p); rd[q-p] = '\0'; q = skip_reg_wthie(q); p = q; q = get_reg_token(p); strncpy(rs, p , q-p); rs[q-p] = '\0'; rd_num = get_reg_index(rd,lines); rs_num = get_reg_index(rs,lines); instruction[counter] = (op_index << 26) | (rd_num << 21) | (rs_num << 16) | 0x0; break; default: break; #endif } counter++; } /* 第二趟汇编 */ struct blist * head; for(int i = 0; i < var_count; i++) { if((head = hash_lookup_item(label_hash,str2hash(var[i].name),&var[i])) != NULL) { label_t * node = head->item; int imm_2 = node->line - var[i].line; if((instruction[var[i].line] >> 26) == JMP) { if(imm_2 > 33554431 || imm_2 < -33554432) { printf("[ERROR 7] line: %d imm num is too lager or too smaller\n",lines); } instruction[var[i].line] |= imm_2 & 0x03ffffff; } else { if(imm_2 > 32767 || imm_2 < -32768) { printf("[ERROR 6] line: %d imm num is too lager or too smaller\n",lines); } instruction[var[i].line] |= imm_2 & 0x0000ffff; } }