void jump(unsigned short addr) { if (swtpc) { pc = addr; return; } else { switch (addr) { /* Too many programs access ACIA directly */ #if 0 case 0xF9CF: case 0xF9DC: /* Output a character */ { term_out(acca); /* putchar(acca); fflush(stdout); */ c_flag = 0; /* Carry is error status */ break; } #endif case 0xFA8B: /* Input a character */ { acca = term_in(); if (!mem[0xFF53]) { /* Echo */ term_out(acca); /* putchar(c); fflush(stdout); */ } else { mem[0xFF53] = 0; } c_flag = 0; /* No error */ break; } case 0xE800: /* OSLOAD (no modified parms) */ { printf("\nOSLOAD...\n"); getsect(0, 0x0020, 23, 128); getsect(0, 0x0020 + 0x0080, 24, 128); pc = 0x0020; sp = 0x00FF; return; } case 0xE822: /* FDINIT (no modified parms) */ { c_flag = 0; break; } #if 0 case 0xF853: /* CHKERR */ { break; } case 0xE85A: /* PRNTER */ { break; } #endif case 0xE869: /* READSC (read full sectors) */ { mem[LSCTLN] = 128; } case 0xE86D: /* READPS (read partial sectors) (FDSTAT, carry, sides) */ { int x; int n = mem[CURDRV]; int first = (mem[STRSCT] << 8) + mem[STRSCT + 1]; int num = (mem[NUMSCT] << 8) + mem[NUMSCT + 1]; int addr = (mem[CURADR] << 8) + mem[CURADR + 1]; int last = mem[LSCTLN]; if (trace_disk) printf("Read sectors: drive=%d, first=%d, number=%d, addr=%x, size of last=%d\n", n, first, num, addr, last); if (check_drive(n)) break; for (x = 0; x != num; ++x) { if (check_sect(n, first + x)) goto oops; getsect(n, addr + 128 * x, first + x, ((x + 1 == num) ? mem[LSCTLN] : 128)); } mem[FDSTAT] = ER_NON; if (drive[n].tracks == 77) mem[SIDES] = 0x80; else mem[SIDES] = 0; c_flag = 0; oops: break; } case 0xE86F: /* RDCRC */ { if (trace_disk) printf("RDCRC\n"); int x; int n = mem[CURDRV]; int first = (mem[STRSCT] << 8) + mem[STRSCT + 1]; int num = (mem[NUMSCT] << 8) + mem[NUMSCT + 1]; int addr = (mem[CURADR] << 8) + mem[CURADR + 1]; int last = mem[LSCTLN]; if (trace_disk) printf("RDCRC: drive=%d, first=%d, number=%d, addr=%x, size of last=%d\n", n, first, num, addr, last); if (check_drive(n)) break; for (x = 0; x != num; ++x) { if (check_sect(n, first + x)) goto oops; } mem[FDSTAT] = ER_NON; if (drive[n].tracks == 77) mem[SIDES] = 0x80; else mem[SIDES] = 0; c_flag = 0; break; } case 0xE875: /* RESTOR */ { int n = mem[CURDRV]; if (trace_disk) printf("RESTOR\n"); if (check_drive(n)) break; mem[FDSTAT] = ER_NON; if (drive[n].tracks == 77) mem[SIDES] = 0x80; else mem[SIDES] = 0; c_flag = 0; break; } case 0xE878: /* SEEK */ { int n = mem[CURDRV]; int first = (mem[STRSCT] << 8) + mem[STRSCT + 1]; if (trace_disk) printf("SEEK\n"); if (check_drive(n)) break; if (check_sect(n, first)) break; if (drive[n].tracks == 77) mem[SIDES] = 0x80; else mem[SIDES] = 0; c_flag = 0; break; } case 0xE872: /* RWTEST */ { if (trace_disk) printf("RWTEST\n"); } case 0xE87B: /* WRTEST */ { unsigned char buf[128]; int x; int n = mem[CURDRV]; int first = (mem[STRSCT] << 8) + mem[STRSCT + 1]; int num = (mem[NUMSCT] << 8) + mem[NUMSCT + 1]; int addr = (mem[CURADR] << 8) + mem[CURADR + 1]; int last = mem[LSCTLN]; if (trace_disk) printf("WRTEST\n"); if (check_drive(n)) break; for (x = 0; x != 128; x += 2) { buf[x] = mem[addr]; buf[x + 1] = mem[addr + 1]; } for(x=0; x != num; ++x) { if (check_sect(n, first + x)) goto oops; if (trace_disk) printf("Wrtest sector %d drive %d\n", first + x, n); fseek(drive[n].f, (first + x) * 128, SEEK_SET); fwrite(buf, 128, 1, drive[n].f); fflush(drive[n].f); } c_flag = 0; if (drive[n].tracks == 77) mem[SIDES] = 0x80; else mem[SIDES] = 0; mem[FDSTAT] = ER_NON; break; } case 0xE87E: /* WRDDAM */ { int n = mem[CURDRV]; printf("\r\nFloppy error: we do not support WRDDAM\n"); c_flag = 1; if (drive[n].tracks == 77) mem[SIDES] = 0x80; else mem[SIDES] = 0; mem[FDSTAT] = ER_WRT; break; } case 0xE884: /* WRITSC */ { if (trace_disk) printf("WRITSC\n"); } case 0xE881: /* WRVERF */ { int x; int n = mem[CURDRV]; int first = (mem[STRSCT] << 8) + mem[STRSCT + 1]; int num = (mem[NUMSCT] << 8) + mem[NUMSCT + 1]; int addr = (mem[CURADR] << 8) + mem[CURADR + 1]; int last = mem[LSCTLN]; if (trace_disk) printf("WRVERF: drive=%d, first=%d, number=%d, addr=%x, size of last=%d\n", n, first, num, addr, last); if (check_drive(n)) break; for(x=0; x != num; ++x) { if (check_sect(n, first + x)) goto oops; putsect(n, addr + 128 * x, first + x, 128); } if (drive[n].tracks == 77) mem[SIDES] = 0x80; else mem[SIDES] = 0; mem[FDSTAT] = ER_NON; c_flag = 0; break; } case 0xE887: /* CLOCK */ { printf("Floppy: Someone called CLOCK?\n"); c_flag = 0; break; } case 0xEBC0: /* LPINIT */ { if (trace_disk) printf("LPINIT\n"); c_flag = 0; break; } case 0xEBCC: /* LIST */ { if (trace_disk) printf("LIST\n"); term_out(acca); /* putchar(acca); fflush(stdout); */ c_flag = 0; break; } case 0xEBE4: /* LDATA */ { if (trace_disk)printf("LDATA\n"); while (mem[ix] != 4) { term_out(mem[ix]); /* putchar(mem[ix]); */ ++ix; } term_out('\r'); term_out('\n'); /* printf("\n"); */ c_flag = 0; break; } case 0xEBF2: /* LDATA1 */ { if (trace_disk) printf("LDATA1\n"); while (mem[ix] != 4) { /* putchar(mem[ix]); */ term_out(mem[ix]); ++ix; } /* fflush(stdout); */ c_flag = 0; break; } default: { pc = addr; return; } } simulated(addr); addr = pull2(); jump(addr); } }
/*eject*/ pboslist() { /* * Process the BLDOUTSC List */ register OUTSECT *osptr; register INSECT *insptr; register INFILE *inflptr; #if !ONEPROC ACTITEM a; #endif OUTSECT *dfn_scn_grp(); long check_sect(); /* * Process the list of output sections. Output sections can be * defined in two places: * * 1. PASS 1: user-supplied; bldcnt will be > 0, and the bldoutsc * list head will be NULL * 2. PASS 2: default-generation; bldcnt will be 0, and the * bldoutsc list will describe the output * sections * * These two uses are mutually exclusive */ #if DEBUG if( dflag > 2 ) fprintf( stderr, "\nBLDOSCN data structures:" ); #endif #if !ONEPROC while( bldcnt-- ) { fread( &a, 1, sizeof(ACTITEM), trnfdes ); a.dfnscn.aiinflnm = (char *) ((int) a.dfnscn.aiinflnm + (int) strbase); if (a.dfnscn.aibndadr != NULL) a.dfnscn.aibndadr = ldlimb( ); if (a.dfnscn.aialign != NULL) a.dfnscn.aialign = ldlimb( ); osptr = dfn_scn_grp(&a, 0); copy(osptr->oshdr.s_name, a.dfnscn.ainame, 8); #if TRVEC /* * User can define attributes of TV in two ways: * (1) using TV { } directive * (2) using SECTIONS { .tv : {} } directive * so force them to agree */ if ( equal(a.dfnscn.ainame, _TV, 8) ) { /* defining .tv */ if ( tvspec.tvbndadr == -1L ) { lineno = a.dfnscn.aiinlnno; curfilnm = a.dfnscn.aiinflnm; tvspec.tvbndadr = eval( a.dfnscn.aibndadr) ; } else a.dfnscn.aibndadr = cnstnode( tvspec.tvbndadr ); } #endif if( a.dfnscn.aitype == AIDFNSCN ) numoutsc++; osptr->oshdr.s_paddr = -1L; listadd(l_OS, &outsclst, osptr); } #endif /* * We now know everything there is to know about the * transfer vector: * At the end of ploadfil(), we knew how big it * had to be. * Here we know whether it was defined by ld or * whether it is defined by .tv input sections * together with a .tv SECTION directive * Go check everything and complete tvspec definition. */ #if TRVEC if ( tvflag ) tvupdat(); /* update definition of tv */ #endif if( bldoutsc.head ) { register ACTITEM *aptr, *a2ptr; aptr = (ACTITEM *) bldoutsc.head; while( aptr ) { osptr = dfn_scn_grp(aptr, 1); copy(osptr->oshdr.s_name, aptr->dfnscn.ainame, 8); if( aptr->dfnscn.aitype == AIDFNSCN ) numoutsc++; osptr->oshdr.s_paddr = -1L; listadd(l_OS, &outsclst, osptr); a2ptr = aptr; aptr = aptr->dfnscn.ainext; free( (char *) a2ptr); } } /* * Make sure all input sections are allocated * into some output section. */ for( inflptr = (INFILE *) infilist.head; inflptr; inflptr = inflptr->flnext ) { for( insptr = inflptr->flishead; insptr; insptr=insptr->isnext ) { if (insptr->isoutsec == 0) { if ((osptr = fndoutsec(insptr->ishdr.s_name)) != NULL) inscadd(insptr,osptr); else { osptr = (OUTSECT *) mycalloc( sizeof( OUTSECT )); numoutsc++; copy(osptr->oshdr.s_name, insptr->ishdr.s_name, 8); osptr->osfill = globfill; osptr->oshdr.s_paddr = -1l; osptr->osnlnno = 1; osptr->osnflnm = "*default*"; listadd(l_OS,&outsclst,osptr); inscadd(insptr,osptr); } } } } /* * for each output section, check the flags, and for a group, * check the size. */ for( osptr = (OUTSECT *) outsclst.head; osptr; osptr = osptr->osnext ) { #if PAGING ACTITEM *aptr; ADDRESS textbegin, textsize; textbegin = hflag + FILHSZ + SCNHSZ * numoutsc + memorg; #endif if (osptr->oshdr.s_flags & STYP_GROUP) { OUTSECT *op; for( op = ((OUTSECT *) osptr->osinclhd); op; op = op->osnext ) { #if PAGING if (bond_t_d && !Nflag && equal(op->oshdr.s_name,_DATA,8)) { osptr->osalign = NULL; aptr = (ACTITEM *) mycalloc(sizeof(ACTITEM)); aptr->bond.aitype = AIBOND; aptr->bond.aiinflnm = "*default.bond.file*"; aptr->bond.aiinlnno = 3; aptr->bond.aioutsec = osptr; aptr->bond.aiadrbnd = cnstnode(((textsize + textbegin) / BOUNDARY + 1) * BOUNDARY + (textsize + textbegin) % K8); listadd(l_AI,&bondlist,aptr); } #endif osptr->oshdr.s_size += check_sect( op ); } if (osptr->oshdr.s_size > MAXSCNSIZE) lderror(1,0,NULL, "GROUP containing section %.8s is too big", osptr->osinclhd->ishdr.s_name); } else { #if PAGING if (bond_t_d && !Nflag && equal(osptr->oshdr.s_name,_TEXT,8)) { textsize = osptr->oshdr.s_size; aptr = (ACTITEM *) mycalloc(sizeof(ACTITEM)); aptr->bond.aitype = AIBOND; aptr->bond.aiinflnm = "*default.bond.file*"; aptr->bond.aiinlnno = 2; aptr->bond.aioutsec = osptr; aptr->bond.aiadrbnd = cnstnode( textbegin ); listadd(l_AI,&bondlist,aptr); } #endif check_sect( osptr ); } } /* * If .tv is user-defined, we now know the true size of * the section ( the sum of the sizes of the input * sections) which we didn't know before. Now call the * the final update routine to insure .tv symtab entry * is correct */ #if TRVEC if ( tvflag ) tvupdt2(); /* final update of tvrange and tvlength */ #endif #if DEBUG if (dflag) dmp_outsects(); #endif }