/* lkrloc3.c */ /* * Copyright (C) 1989-2010 Alan R. Baldwin * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * * Alan R. Baldwin * 721 Berkeley St. * Kent, Ohio 44240 * * With enhancements from: * * John L. Hartman (JLH) * jhartman@compuserve.com * * Bill McKinnon (BM) * w_mckinnon@conknet.com */ #include "aslink.h" /*)Module lkrloc3.c * * The module lkrloc3.c contains the functions which * perform the version 3 relocation calculations. * * lkrloc3.c contains the following functions: * a_uint adb_lo() * a_uint adb_hi() * VOID erpdmp3() * VOID errdmp3() * VOID rele3() * VOID relerr3() * VOID relerp3() * VOID reloc3() * VOID relp3() * VOID relr3() * VOID relt3() * * lkrloc3.c the local variable errmsg3[]. * */ /*)Function VOID reloc3(c) * * int c process code * * The function reloc3() calls a particular relocation * function determined by the process code. * * local variable: * none * * global variables: * int lkerr error flag * * called functions: * int fprintf() c_library * VOID rele3() lkrloc3.c * VOID relp3() lkrloc3.c * VOID relr3() lkrloc3.c * VOId relt3() lkrloc3.c * * side effects: * Refer to the called relocation functions. * */ VOID reloc3(int c) { switch(c) { case 'T': relt3(); break; case 'R': relr3(); break; case 'P': relp3(); break; case 'E': rele3(); break; default: fprintf(stderr, "Undefined Relocation Operation\n"); lkerr++; break; } } /*)Function VOID relt3() * * The function relt3() evaluates a T line read by * the linker. Each byte value read is saved in the * rtval[] array, rtflg[] is set, and the number of * evaluations is maintained in rtcnt. * * T Line * * T xx xx nn nn nn nn nn ... * * * In: "T n0 n1 n2 n3 ... nn" * * Out: 0 1 2 .. rtcnt * +----+----+----+----+----+ * rtval | n0 | n1 | n2 | .. | nn | * +----+----+----+----+----+ * rtflag| 1 | 1 | 1 | 1 | 1 | * +----+----+----+----+----+ * * The T line contains the assembled code output by the assem- * bler with xx xx being the offset address from the current area * base address and nn being the assembled instructions and data in * byte format. * * local variable: * none * * global variables: * int rtcnt number of values evaluated * int rtflg[] array of evaluation flags * int rtval[] array of evaluation values * * called functions: * int eval() lkeval.c * int more() lklex.c * * side effects: * Linker input T line evaluated. * */ VOID relt3(void) { rtcnt = 0; while (more()) { if (rtcnt < NTXT) { rtval[rtcnt] = eval(); rtflg[rtcnt] = 1; rterr[rtcnt] = 0; rtcnt++; } } } /*)Function VOID relr3() * * The function relr3() evaluates a R line read by * the linker. The R line data is combined with the * previous T line data to perform the relocation of * code and data bytes. The S19 / IHX output and * translation of the LST files to RST files may be * performed. * * R Line * * R 0 0 nn nn n1 n2 xx xx ... * * The R line provides the relocation information to the linker. * The nn nn value is the current area index, i.e. which area the * current values were assembled. Relocation information is en- * coded in groups of 4 bytes: * * 1. n1 is the relocation mode and object format * 1. bit 0 word(0x00)/byte(0x01) * 2. bit 1 relocatable area(0x00)/symbol(0x02) * 3. bit 2 normal(0x00)/PC relative(0x04) relocation * 4. bit 3 1-byte(0x00)/2-byte(0x08) byte data * 5. bit 4 signed(0x00)/unsigned(0x10) byte data * 6. bit 5 normal(0x00)/page '0'(0x20) reference * 7. bit 6 normal(0x00)/page 'nnn'(0x40) reference * * 2. n2 is a byte index into the corresponding (i.e. pre- * ceeding) T line data (i.e. a pointer to the data to be * updated by the relocation). The T line data may be * 1-byte or 2-byte byte data format or 2-byte word * format. * * 3. xx xx is the area/symbol index for the area/symbol be- * ing referenced. the corresponding area/symbol is found * in the header area/symbol lists. * * The groups of 4 bytes are repeated for each item requiring relo- * cation in the preceeding T line. * * local variable: * areax **a pointer to array of area pointers * int aindex area index * char *errmsg3[] array of pointers to error strings * int error error code * int mode relocation mode * adrr_t paga paging base area address * a_uint pags paging symbol address * a_uint r PCR relocation value * a_uint reli relocation initial value * a_uint relv relocation final value * int rindex symbol / area index * a_uint rtbase base code address * a_uint rtofst rtval[] index offset * int rtp index into T data * sym **s pointer to array of symbol pointers * * global variables: * head *hp pointer to the head structure * int lkerr error flag * a_uint pc relocated base address * int pcb bytes per instruction word * rerr rerr linker error structure * FILE *stderr standard error device * * called functions: * a_uint adb_1b() lkrloc.c * a_uint adb_2b() lkrloc.c * a_uint adb_lo() lkrloc3.c * a_uint adb_hi() lkrloc3.c * sdld specific * VOID elf() lkelf.c * VOID gb() lkgb.c * end sdld specific * a_uint evword() lkrloc.c * int eval() lkeval.c * int fprintf() c_library * VOID ihx() lkihx.c * VOID s19() lks19.c * VOID lkulist lklist.c * int more() lklex.c * VOID relerr3() lkrloc3.c * int symval() lksym.c * * side effects: * The R and T lines are combined to produce * relocated code and data. Output Sxx / Ixx * and relocated listing files may be produced. * */ VOID relr3(void) { int mode; a_uint reli, relv; int aindex, rindex, rtp, error, i; a_uint r, rtbase, rtofst, paga = 0, pags = 0; struct areax **a; struct sym **s; /* * Get area and symbol lists */ a = hp->a_list; s = hp->s_list; /* * Verify Area Mode */ if (eval() != (R3_WORD | R3_AREA) || eval()) { fprintf(stderr, "R input error\n"); lkerr++; return; } /* * Get area pointer */ aindex = (int) evword(); if (aindex >= hp->h_narea) { fprintf(stderr, "R area error\n"); lkerr++; return; } /* * Select Output File */ if (oflag != 0) { ap = a[aindex]->a_bap; if (ofp != NULL) { rtabnk->b_rtaflg = rtaflg; if (ofp != ap->a_ofp) { lkflush(); } } ofp = ap->a_ofp; rtabnk = ap->a_bp; rtaflg = rtabnk->b_rtaflg; } /* * Base values */ rtbase = adb_xb(0, 0); rtofst = a_bytes; /* * Relocate address */ pc = adb_xb(a[aindex]->a_addr, 0); /* * Number of 'bytes' per PC address */ pcb = 1; #if 0 printf("area %d base address: 0x%x size: 0x%x rtbase: 0x%x\n", aindex, a[aindex]->a_addr, a[aindex]->a_size, rtbase); #endif /* * Do remaining relocations */ while (more()) { error = 0; mode = (int) eval(); if ((mode & R_ESCAPE_MASK) == R_ESCAPE_MASK) { mode = ((mode & ~R_ESCAPE_MASK) << 8) | eval(); /* printf("unescaping rmode\n"); */ } rtp = (int) eval(); rindex = (int) evword(); /* * R3_SYM or R3_AREA references */ if (mode & R3_SYM) { if (rindex >= hp->h_nsym) { fprintf(stderr, "R symbol error\n"); lkerr++; return; } reli = symval(s[rindex]); } /* sdld specific */ else if ((IS_R_J11(mode) || IS_R_J19(mode)) && (rindex == 0xFFFF)) { /* absolute acall/ajmp address */ reli = 0; } /* end sdld specific */ else { if (rindex >= hp->h_narea) { fprintf(stderr, "R area error\n"); lkerr++; return; } reli = a[rindex]->a_addr; } /* * R3_PCR addressing */ if (mode & R3_PCR) { if (mode & R3_BYTE) { reli -= (pc + (rtp-rtofst) + 1); } else { reli -= (pc + (rtp-rtofst) + 2); } } /* * R3_PAG0 or R3_PAG addressing */ if (mode & (R3_PAG0 | R3_PAG)) { paga = sdp.s_area->a_addr; pags = sdp.s_addr; reli -= paga + pags; } /* pdk instruction fusion */ if (TARGET_IS_PDK) { relv = adb_3b(reli, rtp); /* pdk addresses in words, not in bytes, * for goto/call instructions and byte selections. */ int jump = 1, mask = 0; if (rtval[rtp + 4] == 15) { jump = rtval[rtp + 3] & 0x70; mask = 0x40; if (get_sdld_target() == TARGET_ID_PDK) { set_sdld_target(TARGET_ID_PDK15); } else if (get_sdld_target() != TARGET_ID_PDK15) { error = 12; } } else if (rtval[rtp + 4] == 14) { jump = rtval[rtp + 3] & 0x38; mask = 0x20; if (get_sdld_target() == TARGET_ID_PDK) { set_sdld_target(TARGET_ID_PDK14); } else if (get_sdld_target() != TARGET_ID_PDK14) { error = 13; } } else if (rtval[rtp + 4] == 13) { jump = rtval[rtp + 3] & 0x1C; mask = 0x10; if (get_sdld_target() == TARGET_ID_PDK) { set_sdld_target(TARGET_ID_PDK13); } else if (get_sdld_target() != TARGET_ID_PDK13) { error = 14; } /* T*SN and SET* instructions for PDK13 needed to * be handled specially since their address is * in between the opcode. */ if ((rtval[rtp + 3] & 0x1F00) == 0x300 || (rtval[rtp + 3] & 0x1F00) == 0x200) { rtval[rtp] <<= 1; } } const int icall = (mask >> 0) | (mask >> 1) | (mask >> 2); const int igoto = (mask >> 0) | (mask >> 1); if (((mode & R3_BYTE) && !(mode & R3_USGN)) || jump == icall || jump == igoto) { /* Addresses cannot be bigger than N - 1 bits. * Any bits that are set past that point are * marker bits that should be not shifted. */ int marker = rtval[rtp + 1] & 0x80; rtval[rtp + 1] &= ~0x80; rtval[rtp] /= 2; rtval[rtp] |= (rtval[rtp + 1] & 1) << 7; rtval[rtp + 1] /= 2; rtval[rtp + 1] |= marker; } const int inst = (rtval[rtp + 3] << 8) | rtval[rtp + 2]; /* Do the actual opcode fusion and ignore the two * bytes taken for the opcode by the assembler. */ if (IS_R_J11(mode)) { rtval[rtp + 2] |= rtval[rtp]; rtval[rtp + 3] |= rtval[rtp + 1]; } else if (mode & R3_MSB) { rtval[rtp + 2] |= rtval[rtp + 1]; rtval[rtp] = rtval[rtp + 1]; rtval[rtp + 1] = 0; } else { rtval[rtp + 2] |= rtval[rtp]; rtval[rtp + 1] = 0; } const int addr = (rtval[rtp + 1] << 8) | rtval[rtp]; static int errorCount = 0; if (vpdkinst(inst, addr, rtval[rtp + 4])) { if (errorCount < 3) { error = 11; } else if (errorCount == 3) { puts("?ASlink-Warning-More instruction address errors omitted"); } ++errorCount; } mode &= ~R3_USGN; rtflg[rtp] = 0; rtflg[rtp + 1] = 0; rtflg[rtp + 4] = 0; rtofst += 3; } /* * R3_BYTE or R3_WORD operation */ else if (mode & R3_BYTE) { if (mode & R_BYT3) { /* This is a three byte address, of which * we will select one byte. */ /* sdld specific */ if (mode & R_BIT) { relv = adb_24_bit(reli, rtp); } /* sdld specific */ else if (mode & R_HIB) { /* printf("24 bit address selecting hi byte.\n"); */ relv = adb_24_hi(reli, rtp); } else if (mode & R3_MSB) { /* Note that in 24 bit mode, R3_MSB * is really the middle byte, not * the most significant byte. * * This is ugly and I can only apologize * for any confusion. */ /* printf("24 bit address selecting middle byte.\n"); */ relv = adb_24_mid(reli, rtp); } else { /* printf("24 bit address selecting lo byte.\n"); */ relv = adb_24_lo(reli, rtp); } } else if (mode & R3_BYTX) { /* This is a two byte address, of * which we will select one byte. */ if (mode & R_BIT) { relv = adb_bit(reli, rtp); } else if (mode & R3_MSB) { relv = adb_hi(reli, rtp); } else { relv = adb_lo(reli, rtp); } } else { relv = adb_1b(reli, rtp); } } else if (IS_R_J11(mode)) { /* * JLH: 11 bit jump destination for 8051. * Forms two byte instruction with * op-code bits in the MIDDLE! * rtp points at 3 byte locus: * first two will get the address, * third one has raw op-code */ /* * Calculate absolute destination * relv must be on same 2K page as pc */ relv = adb_2b(reli, rtp); if ((relv & ~((a_uint) 0x000007FF)) != ((pc + rtp - rtofst) & ~((a_uint) 0x000007FF))) { error = 6; } /* * Merge MSB with op-code, * ignoring top 5 bits of address. * Then hide the op-code. */ rtval[rtp] = ((rtval[rtp] & 0x07)<<5) | rtval[rtp+2]; rtflg[rtp + 2] = 0; rtofst += 1; } else if (IS_R_J19(mode)) { /* * BK: 19 bit jump destination for DS80C390. * Forms four byte instruction with * op-code bits in the MIDDLE! * rtp points at 4 byte locus: * first three will get the address, * fourth one has raw op-code */ relv = adb_3b(reli, rtp); /* * Calculate absolute destination * relv must be on same 512K page as pc */ if ((relv & ~((a_uint) 0x0007FFFF)) != ((pc + rtp - rtofst) & ~((a_uint) 0x0007FFFF))) { error = 7; } /* * Merge MSB with op-code, * ignoring top 5 bits of address. * Then hide the op-code. */ rtval[rtp] = ((rtval[rtp] & 0x07)<<5) | rtval[rtp+3]; rtflg[rtp + 3] = 0; rtofst += 1; } else if (IS_C24(mode)) { /* * 24 bit destination */ relv = adb_3b(reli, rtp); } else { /* 16 bit address. */ relv = adb_2b(reli, rtp); } /* * R3_BYTE with R3_BYTX offset adjust */ if (mode & R3_BYTE) { if (mode & R3_BYTX) { rtofst += (a_bytes - 1); } } /* * Unsigned Byte Checking */ if (mode & R3_USGN && mode & R3_BYTE && relv & ~((a_uint) 0x000000FF)) error = 1; /* * PCR Relocation Error Checking */ if (mode & R3_PCR && mode & R3_BYTE) { r = relv & ~0x7F; if (r != (a_uint) ~0x7F && r != 0) error = 2; } /* * Page Relocation Error Checking */ if ((TARGET_IS_GB || TARGET_IS_Z80) && mode & R3_PAG0 && (relv & ~0xFF || paga || pags)) error = 4; if (mode & R3_PAG && (relv & ~0xFF)) error = 5; /* sdld specific */ if ((mode & R_BIT) && (relv & ~0x87FF)) error = 10; /* end sdld specific */ /* * Error Processing */ if (error) { rerr.aindex = aindex; rerr.mode = mode; rerr.rtbase = rtbase + rtp - rtofst - 1; rerr.rindex = rindex; rerr.rval = relv - reli; relerr3(errmsg3[error]); for (i=rtp; ia_list; s = hp->s_list; /* * Verify Area Mode */ if (eval() != (R3_WORD | R3_AREA) || eval()) { fprintf(stderr, "P input error\n"); lkerr++; } /* * Get area pointer */ aindex = (int) evword(); if (aindex >= hp->h_narea) { fprintf(stderr, "P area error\n"); lkerr++; return; } /* * Do remaining relocations */ while (more()) { mode = (int) eval(); rtp = (int) eval(); rindex = (int) evword(); /* * R3_SYM or R3_AREA references */ if (mode & R3_SYM) { if (rindex >= hp->h_nsym) { fprintf(stderr, "P symbol error\n"); lkerr++; return; } relv = symval(s[rindex]); } else { if (rindex >= hp->h_narea) { fprintf(stderr, "P area error\n"); lkerr++; return; } relv = a[rindex]->a_addr; } adb_2b(relv, rtp); } /* * Paged values */ aindex = (int) adb_2b(0, 2); if (aindex >= hp->h_narea) { fprintf(stderr, "P area error\n"); lkerr++; return; } sdp.s_areax = a[aindex]; sdp.s_area = sdp.s_areax->a_bap; sdp.s_addr = adb_2b(0, 4); if (sdp.s_area->a_addr & 0xFF || sdp.s_addr & 0xFF) relerp3("Page Definition Boundary Error"); } /*)Function VOID rele3() * * The function rele3() closes all open output files * at the end of the linking process. * * local variable: * none * * global variables: * int oflag output type flag * int uflag relocation listing flag * * called functions: * VOID lkfclose() lkbank.c * VOID lkflush() lkout.c * VOID lkulist() lklist.c * * side effects: * All open output files are closed. * */ VOID rele3() { if (uflag != 0) { lkulist(0); } if (oflag != 0) { lkflush(); lkfclose(); } } /*)Function VOID relerr3(str) * * char *str error string * * The function relerr3() outputs the error string to * stderr and to the map file (if it is open). * * local variable: * none * * global variables: * FILE *mfp handle for the map file * * called functions: * VOID errdmp3() lkrloc3.c * * side effects: * Error message inserted into map file. * */ VOID relerr3(char *str) { errdmp3(stderr, str); if (mfp) errdmp3(mfp, str); } /*)Function VOID errdmp3(fptr, str) * * FILE *fptr output file handle * char *str error string * * The function errdmp3() outputs the error string str * to the device specified by fptr. Additional information * is output about the definition and referencing of * the symbol / area error. * * local variable: * int mode error mode * int aindex area index * int lkerr error flag * int rindex error index * sym **s pointer to array of symbol pointers * areax **a pointer to array of area pointers * areax *raxp error area extension pointer * * global variables: * sdp sdp base page structure * * called functions: * int fprintf() c_library * VOID prntval() lkrloc.c * * side effects: * Error reported. * */ const char errdmp3_null_srcname[] = ""; VOID errdmp3(FILE *fptr, char *str) { int mode, aindex, rindex; struct sym **s; struct areax **a; struct areax *raxp; a = hp->a_list; s = hp->s_list; mode = rerr.mode; aindex = rerr.aindex; rindex = rerr.rindex; /* * Print Error */ fprintf(fptr, "\n?ASlink-Warning-%s", str); lkerr++; /* * Print symbol if symbol based */ if (mode & R3_SYM) { fprintf(fptr, " for symbol %s\n", &s[rindex]->s_id[0]); } else { fprintf(fptr, "\n"); } /* * Print Ref Info */ /* 11111111112222222222333333333344444444445555555555666666666677777*/ /*12345678901234567890123456789012345678901234567890123456789012345678901234*/ /* | | | | */ fprintf(fptr, " file module area offset\n"); fprintf(fptr, " Refby %-14.14s %-14.14s %-14.14s ", (hp->h_lfile && hp->h_lfile->f_idp) ? hp->h_lfile->f_idp : errdmp3_null_srcname, &hp->m_id[0], &a[aindex]->a_bap->a_id[0]); prntval(fptr, rerr.rtbase); /* * Print Def Info */ if (mode & R3_SYM) { raxp = s[rindex]->s_axp; } else { raxp = a[rindex]; } /* 11111111112222222222333333333344444444445555555555666666666677777*/ /*12345678901234567890123456789012345678901234567890123456789012345678901234*/ /* | | | | */ fprintf(fptr, " Defin %-14.14s %-14.14s %-14.14s ", (raxp->a_bhp->h_lfile && raxp->a_bhp->h_lfile->f_idp) ? raxp->a_bhp->h_lfile->f_idp : errdmp3_null_srcname, &raxp->a_bhp->m_id[0], &raxp->a_bap->a_id[0]); if (mode & R3_SYM) { prntval(fptr, s[rindex]->s_addr); } else { prntval(fptr, rerr.rval); } } /*)Function VOID relerp3(str) * * char *str error string * * The function relerp3() outputs the paging error string to * stderr and to the map file (if it is open). * * local variable: * none * * global variables: * FILE *mfp handle for the map file * * called functions: * VOID erpdmp3() lkrloc3.c * * side effects: * Error message inserted into map file. * */ VOID relerp3(char *str) { erpdmp3(stderr, str); if (mfp) erpdmp3(mfp, str); } /*)Function VOID erpdmp3(fptr, str) * * FILE *fptr output file handle * char *str error string * * The function erpdmp3() outputs the error string str * to the device specified by fptr. * * local variable: * head *thp pointer to head structure * * global variables: * int lkerr error flag * sdp sdp base page structure * * called functions: * int fprintf() c_library * VOID prntval() lkrloc.c * * side effects: * Error reported. * */ VOID erpdmp3(FILE *fptr, char *str) { struct head *thp; thp = sdp.s_areax->a_bhp; /* * Print Error */ fprintf(fptr, "\n?ASlink-Warning-%s\n", str); lkerr++; /* * Print PgDef Info */ /* 111111111122222222223333333333444444444455555555556666666666777*/ /*123456789012345678901234567890123456789012345678901234567890123456789012*/ fprintf(fptr, " file module pgarea pgoffset\n"); fprintf(fptr, " PgDef %-14.14s %-14.14s %-14.14s ", thp->h_lfile->f_idp, &thp->m_id[0], &sdp.s_area->a_id[0]); prntval(fptr, sdp.s_area->a_addr + sdp.s_addr); } /* sdld specific */ /*)Function a_uint adb_bit(v, i) * * a_uint v value to add to byte * int i rtval[] index * * The function adb_bit() converts the single * byte address value contained in rtval[i] to bit- * addressable space and adds the value of v to it. * The new value of rtval[i] is returned. * * local variable: * a_uint j temporary evaluation variable * * global variables: * none * * called functions: * none * * side effects: * The value of rtval[] is changed. * */ a_uint adb_bit(a_uint v, int i) { a_uint j; j = adb_lo(v, i) & 0xFF; if ((j >= 0x20) && (j <= 0x2F)) { j = (j - 0x20) * 8; } else if ((j < 0x80) || ((j & 0x07) != 0)) { return(0x100);//error } if (hilo) { j = rtval[i+1] = j + (rtval[i] & 0x07); } else { j = rtval[i] = j + (rtval[i+1] & 0x07); } return(j); } /* end sdld specific */ /*)Function a_uint adb_lo(v, i) * * int v value to add to byte * int i rtval[] index * * The function adb_lo() adds the value of v to the * value contained in rtval[i] through rtval[i + a_bytes - 1]. * The new value of rtval[i] ... is returned. * The rtflg[] flags are cleared for all rtval[i] ... except * the LSB. * * local variable: * a_uint j temporary evaluation variable * * global variables: * hilo byte ordering parameter * * called functions: * none * * side effects: * The value of rtval[] is changed. * The rtflg[] values corresponding to all bytes * except the LSB of the value are cleared to reflect * the fact that the LSB is the selected byte. * */ a_uint adb_lo(v, i) a_uint v; int i; { a_uint j; int m, n; j = adb_xb(v, i); /* * LSB is lowest order byte of data */ m = (hilo ? a_bytes-1 : 0); for (n=0; n= 0x20) && (j <= 0x2F)) { j = (j - 0x20) * 8; } else if ((j < 0x80) || ((j & 0x07) != 0)) { return(0x100);//error } if (hilo) { j = rtval[i+2] = j + (rtval[i+1] & 0x07); } else { j = rtval[i] = j + (rtval[i+1] & 0x07); } return(j); } /*)Function a_uint adb_24_hi(v, i) * * a_uint v value to add to byte * int i rtval[] index * * The function adb_24_hi() adds the value of v to the * 24 bit value contained in rtval[i] - rtval[i+2]. * The new value of rtval[i] / rtval[i+1] is returned. * The LSB & middle byte rtflg[] is cleared. * * local variable: * a_uint j temporary evaluation variable * * global variables: * hilo byte ordering parameter * * called functions: * none * * side effects: * The value of rtval[] is changed. * The rtflg[] value corresponding to the * LSB & middle byte of the word value is cleared to * reflect the fact that the MSB is the selected byte. * */ a_uint adb_24_hi(v, i) a_uint v; int i; { a_uint j; j = adb_3b(v, i); /* Remove the lower two bytes. */ if (hilo) { rtflg[i+2] = 0; } else { rtflg[i] = 0; } rtflg[i+1] = 0; return (j); } /*)Function a_uint adb_24_mid(v, i) * * a_uint v value to add to byte * int i rtval[] index * * The function adb_24_mid() adds the value of v to the * 24 bit value contained in rtval[i] - rtval[i+2]. * The new value of rtval[i] / rtval[i+1] is returned. * The LSB & MSB byte rtflg[] is cleared. * * local variable: * a_uint j temporary evaluation variable * * global variables: * hilo byte ordering parameter * * called functions: * none * * side effects: * The value of rtval[] is changed. * The rtflg[] value corresponding to the * LSB & MSB of the 24 bit value is cleared to reflect * the fact that the middle byte is the selected byte. * */ a_uint adb_24_mid(v, i) a_uint v; int i; { a_uint j; j = adb_3b(v, i); /* remove the MSB & LSB. */ rtflg[i+2] = 0; rtflg[i] = 0; return (j); } /*)Function a_uint adb_24_lo(v, i) * * a_uint v value to add to byte * int i rtval[] index * * The function adb_24_lo() adds the value of v to the * 24 bit value contained in rtval[i] - rtval[i+2]. * The new value of rtval[i] / rtval[i+1] is returned. * The MSB & middle byte rtflg[] is cleared. * * local variable: * a_uint j temporary evaluation variable * * global variables: * hilo byte ordering parameter * * called functions: * none * * side effects: * The value of rtval[] is changed. * The rtflg[] value corresponding to the * MSB & middle byte of the word value is cleared to * reflect the fact that the LSB is the selected byte. * */ a_uint adb_24_lo(v, i) a_uint v; int i; { a_uint j; j = adb_3b(v, i); /* Remove the upper two bytes. */ if (hilo) { rtflg[i] = 0; } else { rtflg[i+2] = 0; } rtflg[i+1] = 0; return (j); } /*)Function VOID vpdkinst(inst, addr, ver) * * int inst instruction * int addr address * int ver PDK version * * The function vpdkinst() tests whether the address * does not exceed the allowed maximum size of the * instruction. * * local variable: * a_uint j temporary evaluation variable * * global variables: * hilo byte ordering parameter * * called functions: * none * * side effects: * The value of rtval[] is changed. * The rtflg[] value corresponding to the * MSB & middle byte of the word value is cleared to * reflect the fact that the LSB is the selected byte. * */ int vpdkinst(inst, addr, ver) int inst; int addr; int ver; { switch (ver) { case 13: /* PDK 13 */ switch (inst & 0x1C00) { case 0x1800: case 0x1C00: if (addr > 0x3FF) { return 1; } break; case 0x1000: case 0x1400: if (addr > 0xFF) { return 1; } break; case 0x0C00: case 0x2000: if (addr > 0x1F) { return 1; } break; case 0x800: case 0x400: if (addr > 0x3F) { return 1; } break; case 0x0: if (inst & 0x200) { /* Address was right shifted to fit into the * opcode. */ if ((addr >> 1) > 0xF) { return 1; } } else if (inst & 0x100) { if (addr > 0xFF) { return 1; } } else if (addr > 0x1F) { return 1; } break; } break; case 14: /* PDK 14 */ switch (inst & 0x3800) { case 0x3000: case 0x3800: if (addr > 0x7FF) { return 1; } break; case 0x2800: if (addr > 0xFF) { return 1; } break; case 0x1800: case 0x2000: if (addr > 0x3F) { return 1; } break; case 0x800: case 0x1000: if (addr > 0x7F) { return 1; } break; case 0x0: if (inst & 0x400) { if (addr > 0x3F) { return 1; } } else if ((inst & 0x300) == 0x300) { if (addr & 0x1) { return 1; } } else if ((inst & 0x300) == 0x200 && addr > 0xFF) { return 1; } else if ((inst & 0x300) == 0x100 && addr > 0x3F) { return 1; } break; } break; case 15: /* PDK 15 */ switch (inst & 0x7000) { case 0x6000: case 0x7000: if (addr > 0xFFF) { return 1; } break; case 0x5000: if (inst & 0x800) { if (addr > 0x7F) { return 1; } break; } case 0x1000: case 0x2000: if (addr > 0xFF) { return 1; } break; case 0x3000: case 0x4000: if (addr > 0x7F) { return 1; } break; case 0x0: switch (inst & 0xC00) { case 0xC00: if (addr > 0xFF) { return 1; } break; case 0x400: if (addr > 0xFF || (addr & 0x1)) { return 1; } break; case 0x0: if ((inst & 0x200) && addr > 0xFF) { return 1; } else if (!(inst & 0x200) && addr > 0x7F) { return 1; } break; } break; } break; } return 0; #undef MASK } /* end sdld specific */