diff --git a/PDP11/pdp11_rs.c b/PDP11/pdp11_rs.c index 82093f90..364bd2b7 100644 --- a/PDP11/pdp11_rs.c +++ b/PDP11/pdp11_rs.c @@ -686,7 +686,7 @@ static const uint16 boot_rom[] = { t_stat rs_boot (int32 unitno, DEVICE *dptr) { -int32 i; +size_t i; extern uint16 *M; UNIT *uptr = rs_dev.units + unitno; diff --git a/VAX/vax780_defs.h b/VAX/vax780_defs.h index 6f509643..11ae9c61 100644 --- a/VAX/vax780_defs.h +++ b/VAX/vax780_defs.h @@ -1,6 +1,6 @@ /* vax780_defs.h: VAX 780 model-specific definitions file - Copyright (c) 2004-2011, Robert M Supnik + Copyright (c) 2004-2013, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -23,6 +23,7 @@ used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 29-Nov-13 RMS Added system-specific unaligned routines 12-Dec-12 RMS Fixed IO base address for RQB, RQC, RQD 05-Nov-11 RMS Added VEC_QMODE definition 19-Nov-08 RMS Moved I/O support routines to I/O library @@ -448,6 +449,14 @@ t_stat show_nexus (FILE *st, UNIT *uptr, int32 val, void *desc); void sbi_set_errcnf (void); int32 clk_cosched (int32 wait); +/* Function prototypes for system-specific unaligned support + 11/780 treats unaligned like aligned */ + +#define ReadIOU(p,l) ReadIO (p,l) +#define ReadRegU(p,l) ReadReg (p,l) +#define WriteIOU(p,v,l) WriteIO (p, v, l) +#define WriteRegU(p,v,l) WriteReg (p, v, l) + #include "pdp11_io_lib.h" #endif diff --git a/VAX/vax_io.c b/VAX/vax_io.c index 8d6baab0..10206dd4 100644 --- a/VAX/vax_io.c +++ b/VAX/vax_io.c @@ -1,6 +1,6 @@ /* vax_io.c: VAX 3900 Qbus IO simulator - Copyright (c) 1998-2012, Robert M Supnik + Copyright (c) 1998-2013, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -25,6 +25,7 @@ qba Qbus adapter + 20-Dec-13 RMS Added unaligned access routines 25-Mar-12 RMS Added parameter to int_ack prototype (Mark Pizzolata) 28-May-08 RMS Inlined physical memory routines 25-Jan-08 RMS Fixed declarations (Mark Pizzolato) @@ -229,7 +230,7 @@ mem_err = 1; return; } -/* ReadIO - read I/O space +/* ReadIO - read I/O space - aligned access Inputs: pa = physical address @@ -250,7 +251,49 @@ SET_IRQL; return iod; } -/* WriteIO - write I/O space +/* ReadIOU - read I/O space - unaligned access + + Inputs: + pa = physical address + lnt = length (1, 2, 3 bytes) + Output: + data, not shifted + +Note that all of these cases are presented to the existing aligned IO routine: + +bo = 0, byte, word, or longword length +bo = 2, word +bo = 1, 2, 3, byte length + +All the other cases are end up at ReadIOU and WriteIOU, and they must turn +the request into the exactly correct number of Qbus accesses AND NO MORE, +because Qbus reads can have side-effects, and word read-modify-write is NOT +the same as a byte write. + +Note that the sum of the pa offset and the length cannot be greater than 4. +The read cases are: + +bo = 0, byte or word - read one word +bo = 0, tribyte - read two words +bo = 1, byte - read one word +bo = 1, word or tribyte - read two words +bo = 2, byte or word - read one word +bo = 3, byte - read one word +*/ + +int32 ReadIOU (uint32 pa, int32 lnt) +{ +int32 iod; + +iod = ReadQb (pa); /* wd from Qbus */ +if ((lnt + (pa & 1)) <= 2) /* byte or (word & even) */ + iod = iod << ((pa & 2)? 16: 0); /* one op */ +else iod = (ReadQb (pa + 2) << 16) | iod; /* two ops, get 2nd wd */ +SET_IRQL; +return iod; +} + +/* WriteIO - write I/O space - aligned access Inputs: pa = physical address @@ -274,6 +317,54 @@ SET_IRQL; return; } +/* WriteIOU - write I/O space + + Inputs: + pa = physical address + val = data to write, right justified in 32b longword + lnt = length (1, 2, or 3 bytes) + Outputs: + none + +The write cases are: + +bo = x, lnt = byte - write one byte +bo = 0 or 2, lnt = word - write one word +bo = 1, lnt = word - write two bytes +bo = 0, lnt = tribyte - write word, byte +bo = 1, lnt = tribyte - write byte, word +*/ + +void WriteIOU (uint32 pa, int32 val, int32 lnt) +{ +switch (lnt) { +case L_BYTE: /* byte */ + WriteQb (pa, val & BMASK, WRITEB); + break; + +case L_WORD: /* word */ + if (pa & 1) { /* odd addr? */ + WriteQb (pa, val & BMASK, WRITEB); + WriteQb (pa + 1, (val >> 8) & BMASK, WRITEB); + } + else WriteQb (pa, val & WMASK, WRITE); + break; + +case 3: /* tribyte */ + if (pa & 1) { /* odd addr? */ + WriteQb (pa, val & BMASK, WRITEB); /* byte then word */ + WriteQb (pa + 1, (val >> 8) & WMASK, WRITE); + } + else { /* even */ + WriteQb (pa, val & WMASK, WRITE); /* word then byte */ + WriteQb (pa + 2, (val >> 16) & BMASK, WRITEB); + } + break; + } +SET_IRQL; +return; +} + /* Find highest priority outstanding interrupt */ int32 eval_int (void) diff --git a/VAX/vax_mmu.c b/VAX/vax_mmu.c index 177b61e8..864085c7 100644 --- a/VAX/vax_mmu.c +++ b/VAX/vax_mmu.c @@ -1,6 +1,6 @@ /* vax_mmu.c - VAX memory management - Copyright (c) 1998-2008, Robert M Supnik + Copyright (c) 1998-2013, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -23,6 +23,7 @@ used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 29-Nov-13 RMS Reworked unaligned flows 21-Jul-08 RMS Removed inlining support 28-May-08 RMS Inlined physical memory routines 29-Apr-07 RMS Added address masking for system page table reads @@ -56,7 +57,6 @@ typedef struct { } TLBENT; extern uint32 *M; -extern const uint32 align[4]; extern int32 PSL; extern int32 mapen; extern int32 p1, p2; @@ -107,6 +107,8 @@ extern int32 ReadIO (uint32 pa, int32 lnt); extern void WriteIO (uint32 pa, int32 val, int32 lnt); extern int32 ReadReg (uint32 pa, int32 lnt); extern void WriteReg (uint32 pa, int32 val, int32 lnt); +int32 ReadU (uint32 pa, int32 lnt); +void WriteU (uint32 pa, int32 val, int32 lnt); /* TLB data structures @@ -192,22 +194,22 @@ if (mapen && ((off + lnt) > VA_PAGSIZE)) { /* cross page? */ if (((xpte.pte & acc) == 0) || (xpte.tag != vpn) || ((acc & TLB_WACC) && ((xpte.pte & TLB_M) == 0))) xpte = fill (va + lnt, lnt, acc, NULL); /* fill if needed */ - pa1 = (xpte.pte & TLB_PFN) | VA_GETOFF (va + 4); + pa1 = ((xpte.pte & TLB_PFN) | VA_GETOFF (va + 4)) & ~03; } -else pa1 = (pa + 4) & PAMASK; /* not cross page */ +else pa1 = ((pa + 4) & PAMASK) & ~03; /* not cross page */ bo = pa & 3; if (lnt >= L_LONG) { /* lw unaligned? */ sc = bo << 3; - wl = ReadL (pa); /* read both lw */ - wh = ReadL (pa1); /* extract */ - return ((((wl >> sc) & align[bo]) | (wh << (32 - sc))) & LMASK); + wl = ReadU (pa, L_LONG - bo); /* read both fragments */ + wh = ReadU (pa1, bo); /* extract */ + return ((wl | (wh << (32 - sc))) & LMASK); } -else if (bo == 1) - return ((ReadL (pa) >> 8) & WMASK); +else if (bo == 1) /* read within lw */ + return ReadU (pa, L_WORD); else { - wl = ReadL (pa); /* word cross lw */ - wh = ReadL (pa1); /* read, extract */ - return (((wl >> 24) & 0xFF) | ((wh & 0xFF) << 8)); + wl = ReadU (pa, L_BYTE); /* word cross lw */ + wh = ReadU (pa1, L_BYTE); /* read, extract */ + return (wl | (wh << 8)); } } @@ -225,7 +227,7 @@ else { void Write (uint32 va, int32 val, int32 lnt, int32 acc) { int32 vpn, off, tbi, pa; -int32 pa1, bo, sc, wl, wh; +int32 pa1, bo, sc; TLBENT xpte; mchk_va = va; @@ -255,29 +257,20 @@ if (mapen && ((off + lnt) > VA_PAGSIZE)) { if (((xpte.pte & acc) == 0) || (xpte.tag != vpn) || ((xpte.pte & TLB_M) == 0)) xpte = fill (va + lnt, lnt, acc, NULL); - pa1 = (xpte.pte & TLB_PFN) | VA_GETOFF (va + 4); + pa1 = ((xpte.pte & TLB_PFN) | VA_GETOFF (va + 4)) & ~03; } -else pa1 = (pa + 4) & PAMASK; +else pa1 = ((pa + 4) & PAMASK) & ~03; bo = pa & 3; -wl = ReadL (pa); if (lnt >= L_LONG) { sc = bo << 3; - wh = ReadL (pa1); - wl = (wl & insert[bo]) | ((val << sc) & LMASK); - wh = (wh & ~insert[bo]) | ((val >> (32 - sc)) & insert[bo]); - WriteL (pa, wl); - WriteL (pa1, wh); + WriteU (pa, val & insert[L_LONG - bo], L_LONG - bo); + WriteU (pa1, (val >> (32 - sc)) & insert[bo], bo); } -else if (bo == 1) { - wl = (wl & 0xFF0000FF) | (val << 8); - WriteL (pa, wl); - } -else { - wh = ReadL (pa1); - wl = (wl & 0x00FFFFFF) | ((val & 0xFF) << 24); - wh = (wh & 0xFFFFFF00) | ((val >> 8) & 0xFF); - WriteL (pa, wl); - WriteL (pa1, wh); +else if (bo == 1) /* read within lw */ + WriteU (pa, val & WMASK, L_WORD); +else { /* word cross lw */ + WriteU (pa, val & BMASK, L_BYTE); + WriteU (pa1, (val >> 8) & BMASK, L_BYTE); } return; } @@ -348,7 +341,8 @@ SIM_INLINE int32 ReadL (uint32 pa) if (ADDR_IS_MEM (pa)) return M[pa >> 2]; mchk_ref = REF_V; -if (ADDR_IS_IO (pa)) return ReadIO (pa, L_LONG); +if (ADDR_IS_IO (pa)) + return ReadIO (pa, L_LONG); return ReadReg (pa, L_LONG); } @@ -363,6 +357,30 @@ if (ADDR_IS_IO (pa)) return ReadReg (pa, L_LONG); } +/* Read unaligned physical (in virtual context) + + Inputs: + pa = physical address + lnt = length in bytes (1, 2, or 3) + Output: + returned data +*/ + +int32 ReadU (uint32 pa, int32 lnt) +{ +int32 dat; +int32 sc = (pa & 3) << 3; +if (ADDR_IS_MEM (pa)) + dat = M[pa >> 2]; +else { + mchk_ref = REF_V; + if (ADDR_IS_IO (pa)) + dat = ReadIOU (pa, lnt); + else dat = ReadRegU (pa, lnt); + } +return ((dat >> sc) & insert[lnt]); +} + /* Write aligned physical (in virtual context, unless indicated) Inputs: @@ -432,6 +450,33 @@ else { return; } +/* Write unaligned physical (in virtual context) + + Inputs: + pa = physical address + val = data to be written, right justified in 32b longword + lnt = length (1, 2, or 3 bytes) + Output: + none +*/ + +void WriteU (uint32 pa, int32 val, int32 lnt) +{ +if (ADDR_IS_MEM (pa)) { + int32 bo = pa & 3; + int32 sc = bo << 3; + M[pa >> 2] = (M[pa >> 2] & ~(insert[lnt] << sc)) | ((val & insert[lnt]) << sc); + } +else { + mchk_ref = REF_V; + if ADDR_IS_IO (pa) + WriteIOU (pa, val, lnt); + else WriteRegU (pa, val, lnt); + } +return; +} + + /* TLB fill This routine fills the TLB after a tag or access mismatch, or diff --git a/VAX/vax_sysdev.c b/VAX/vax_sysdev.c index fc494d13..f12cf97b 100644 --- a/VAX/vax_sysdev.c +++ b/VAX/vax_sysdev.c @@ -1,6 +1,6 @@ /* vax_sysdev.c: VAX 3900 system-specific logic - Copyright (c) 1998-2011, Robert M Supnik + Copyright (c) 1998-2013, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -32,6 +32,7 @@ cso console storage output sysd system devices (SSC miscellany) + 20-Dec-13 RMS Added unaligned register space access routines 23-Dec-10 RMS Added power clear call to boot routine (Mark Pizzolato) 25-Oct-05 RMS Automated CMCTL extended memory 16-Aug-05 RMS Fixed C++ declaration and cast problems @@ -214,6 +215,9 @@ int32 ssc_adsm[2] = { 0 }; /* addr strobes */ int32 ssc_adsk[2] = { 0 }; int32 cdg_dat[CDASIZE >> 2]; /* cache data */ static uint32 rom_delay = 0; +static const int32 insert[4] = { + 0x00000000, 0x000000FF, 0x0000FFFF, 0x00FFFFFF + }; t_stat rom_ex (t_value *vptr, t_addr exta, UNIT *uptr, int32 sw); t_stat rom_dep (t_value val, t_addr exta, UNIT *uptr, int32 sw); @@ -961,6 +965,20 @@ MACH_CHECK (MCHK_READ); return 0; } +/* ReadRegU - read register space, unaligned + + Inputs: + pa = physical address + lnt = length in bytes (1, 2, or 3) + Output: + returned data, not shifted +*/ + +int32 ReadRegU (uint32 pa, int32 lnt) +{ +return ReadReg (pa & ~03, L_LONG); +} + /* WriteReg - write register space Inputs: @@ -986,6 +1004,26 @@ MACH_CHECK (MCHK_WRITE); return; } +/* WriteRegU - write register space, unaligned + + Inputs: + pa = physical address + val = data to write, right justified in 32b longword + lnt = length (1, 2, or 3) + Outputs: + none +*/ + +void WriteRegU (uint32 pa, int32 val, int32 lnt) +{ +int32 sc = (pa & 03) << 3; +int32 dat = ReadReg (pa & ~03, L_LONG); + +dat = (dat & ~(insert[lnt] << sc)) | ((val & insert[lnt]) << sc); +WriteReg (pa & ~03, dat, L_LONG); +return; +} + /* CMCTL registers CMCTL00 - 15 configure memory banks 00 - 15. Note that they are diff --git a/VAX/vaxmod_defs.h b/VAX/vaxmod_defs.h index 3b1ad070..34360446 100644 --- a/VAX/vaxmod_defs.h +++ b/VAX/vaxmod_defs.h @@ -1,6 +1,6 @@ /* vaxmod_defs.h: VAX model-specific definitions file - Copyright (c) 1998-2012, Robert M Supnik + Copyright (c) 1998-2013, Robert M Supnik Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), @@ -23,6 +23,7 @@ used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from Robert M Supnik. + 20-Dec-13 RMS Added prototypes for unaligned IO and register handling 12-Dec-12 RMS Fixed IO base address for RQB, RQC, RQD 11-Dec-11 RMS Moved all Qbus devices to BR4; deleted RP definitions 25-Nov-11 RMS Added VEC_QBUS definition @@ -471,4 +472,11 @@ int32 clk_cosched (int32 wait); #include "pdp11_io_lib.h" +/* Function prototypes for system-specific unaligned support */ + +int32 ReadIOU (uint32 pa, int32 lnt); +int32 ReadRegU (uint32 pa, int32 lnt); +void WriteIOU (uint32 pa, int32 val, int32 lnt); +void WriteRegU (uint32 pa, int32 val, int32 lnt); + #endif