mirror of
https://github.com/mikpe/pdp10-tools.git
synced 2026-02-26 08:53:41 +00:00
sim: add effective address calculation
This commit is contained in:
@@ -20,7 +20,7 @@ CC=gcc
|
||||
CFLAGS=-O2 -g -Wall
|
||||
CPPFLAGS=-I../include
|
||||
|
||||
SIMOBJS=sim.o pdp10-virt-mem.o
|
||||
SIMOBJS=sim.o pdp10-virt-mem.o pdp10-ea.o
|
||||
LIBOBJS=../lib/pdp10-elf36.o ../lib/pdp10-extint.o ../lib/pdp10-stdio.o
|
||||
|
||||
sim: $(SIMOBJS) $(LIBOBJS)
|
||||
|
||||
173
sim/pdp10-ea.c
Normal file
173
sim/pdp10-ea.c
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* pdp10-ea.c -- PDP10 Effective-Address Calculation
|
||||
* Copyright (C) 2018 Mikael Pettersson
|
||||
*
|
||||
* This file is part of pdp10-tools.
|
||||
*
|
||||
* pdp10-tools 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.
|
||||
*
|
||||
* pdp10-tools 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 pdp10-tools. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pdp10-core.h"
|
||||
#include "pdp10-arith.h"
|
||||
|
||||
/* c.f. Figure 1.9 in the Toad-1 Architecture Manual */
|
||||
static
|
||||
uint64_t pdp10_section_zero_ea(struct pdp10_cpu *cpu, uint64_t MB)
|
||||
{
|
||||
|
||||
/* Instruction Fetch (not done here)
|
||||
*
|
||||
* MB := C(PC)
|
||||
* IR := MB_<0:12>
|
||||
*/
|
||||
|
||||
for (;;) {
|
||||
uint32_t Y = BITS36(MB, 18, 35); /* Y := MB_<18:35> */
|
||||
unsigned int X = BITS36(MB, 14, 17); /* X := MB_<14:17> */
|
||||
unsigned int I = BIT36(MB, 13); /* I := MB_<13> */
|
||||
uint32_t E; /* 18 bits */
|
||||
|
||||
if (X == 0) {
|
||||
E = Y;
|
||||
} else {
|
||||
E = BITS36LOW18(Y + BITS36LOW18(cpu->AC[X])); /* E := Y + C(X)_<18:35> */
|
||||
}
|
||||
|
||||
if (I == 0) {
|
||||
return E;
|
||||
}
|
||||
|
||||
/* MB := C(E), but handle ACs */
|
||||
if (E <= 017) {
|
||||
MB = cpu->AC[E];
|
||||
} else {
|
||||
MB = pdp10_vmem_read(&cpu->vmem, E);
|
||||
if (MB == (uint64_t)-1)
|
||||
return MB; /* propagate page fault */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* c.f. Figure 1.11 in the Toad-1 Architecture Manual */
|
||||
static
|
||||
uint64_t pdp10_extended_ea(struct pdp10_cpu *cpu, uint64_t MB)
|
||||
{
|
||||
uint32_t E; /* 30 bits */
|
||||
|
||||
/* Instruction Fetch (not done here)
|
||||
*
|
||||
* if PC_<18:31> == 0 then MB := C(PC_<32:35>)
|
||||
* else MB := C(PC_<6:35>)
|
||||
* IR := MB_<0:12>
|
||||
*/
|
||||
E = BITS36(cpu->PC, 6, 17) << 18; /* E_<6:17> := PC_<6:17> */
|
||||
|
||||
/* Local-Format Address Word */
|
||||
/* A Local Address is in the same section as this Address Word */
|
||||
|
||||
for (;;) {
|
||||
unsigned int I = BIT36(MB, 13); /* I := MB_<13> */
|
||||
{
|
||||
uint32_t Y = BITS36(MB, 18, 35); /* Y_<18:35> := MB_<18:35> */
|
||||
unsigned int X = BITS36(MB, 14, 17); /* X := MB_<14:17> */
|
||||
/* Indexed Address? Test X field. */
|
||||
if (X == 0) {
|
||||
/* No Indexing */
|
||||
E = BITS36(E, 6, 17) | Y; /* E_<18:35> := Y_<18:35> */
|
||||
} else {
|
||||
/* X field != 0 */
|
||||
pdp10_uint36_t CX = cpu->AC[X];
|
||||
/* Test Section Number in E_<6:17> */
|
||||
if (BITS36(E, 6, 17) == 0) { /* Section 0 */
|
||||
/* Local Index */
|
||||
E = BITS36(E, 6, 17) | BITS36LOW18(CX + Y); /* E_<18:35> := C(X)_<18:35> + Y_<18:35> */
|
||||
} else {
|
||||
/* Section != 0 */
|
||||
/* Test C(X). Global Index when (C(X)_<0> == 0) && (C(X)_<6:17> != 0) */
|
||||
if (!(BIT36(CX, 0) == 0 && BITS36(CX, 6, 17) != 0)) {
|
||||
/* Local Index */
|
||||
E = BITS36(E, 6, 17) | BITS36LOW18(CX + Y); /* E_<18:35> := C(X)_<18:35> + Y_<18:35> */
|
||||
} else {
|
||||
/* Global Index */
|
||||
Y = pdp10_sext_uint18(Y); /* Y_<6:17> := 07777 * Y_<18> */
|
||||
E = BITS36((CX + Y), 6, 35); /* E_<6:35> := C(X)_<6:35> + Y_<6:35> */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
/* Indirect Addressing? Test I bit. */
|
||||
if (I == 0) { /* Done! */
|
||||
/* E is the Effective Address */
|
||||
/* The "XCT Continues" loop is implemented by the caller. */
|
||||
return E;
|
||||
}
|
||||
/* Fetch the Indirect Word: MB := C(E) */
|
||||
/* FIXME: handle ACs? */
|
||||
MB = pdp10_vmem_read(&cpu->vmem, E);
|
||||
if (MB == (uint64_t)-1)
|
||||
return MB; /* propagate page fault */
|
||||
/* Non-Zero Section? Test E_<6:17> */
|
||||
if (BITS36(E, 6, 17) == 0) {
|
||||
/* Section 0 */
|
||||
break;
|
||||
} else {
|
||||
/* Section != 0 */
|
||||
/* Decode Indirect Word MB_<0:1> */
|
||||
switch (BITS36(MB, 0, 1)) {
|
||||
case 2:
|
||||
/* Local Indirect */
|
||||
break;
|
||||
case 3:
|
||||
/* Page Failure */
|
||||
return (uint64_t)-1;
|
||||
case 0:
|
||||
case 1: {
|
||||
/* Global Indirect Word */
|
||||
uint32_t Y = BITS36(MB, 6, 35); /* Y := MB_<6:35> */
|
||||
unsigned int X = BITS36(MB, 2, 5); /* X := MB_<2:5> */
|
||||
I = BIT36(MB, 1); /* I := MB_<1> */
|
||||
/* Indexed Address? Test X field. */
|
||||
if (X == 0) {
|
||||
E = Y; /* E_<6:35> := Y_<6:35> */
|
||||
} else {
|
||||
E = BITS36((cpu->AC[X] + Y), 6, 35); /* E_<6:35> := C(X)_6:35 + Y_<6:35> */
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
int pdp10_section_zero_p(struct pdp10_cpu *cpu)
|
||||
{
|
||||
/* My interpretation is that the choice of EA procedure is only based on
|
||||
* whether the CPU is extended or not, so an extended CPU should always
|
||||
* use the extended EA procedure, regardless of which section PC is in.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t pdp10_ea(struct pdp10_cpu *cpu, uint64_t MB)
|
||||
{
|
||||
if (pdp10_section_zero_p(cpu))
|
||||
return pdp10_section_zero_ea(cpu, MB);
|
||||
else
|
||||
return pdp10_extended_ea(cpu, MB);
|
||||
}
|
||||
31
sim/pdp10-ea.h
Normal file
31
sim/pdp10-ea.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* pdp10-ea.h -- PDP10 Effective-Address Calculation
|
||||
* Copyright (C) 2018 Mikael Pettersson
|
||||
*
|
||||
* This file is part of pdp10-tools.
|
||||
*
|
||||
* pdp10-tools 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.
|
||||
*
|
||||
* pdp10-tools 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 pdp10-tools. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef PDP10_EA_H
|
||||
#define PDP10_EA_H
|
||||
|
||||
#include "pdp10-core.h"
|
||||
|
||||
/* This performs Effective Address Calculation, but not Instruction Fetch
|
||||
* or looping on XCT instructions; the caller is assumed to handle that.
|
||||
* Returns (uint64_t)-1 on failure (page fault), a pdp10_uint36_t word on success.
|
||||
*/
|
||||
uint64_t pdp10_ea(struct pdp10_cpu *cpu, uint64_t MB);
|
||||
|
||||
#endif /* PDP10_EA_H */
|
||||
Reference in New Issue
Block a user