Search code examples
assemblyemulationsimulatorbare-metalpdp-11

Beginner bare-metal pdp11 console output


I am trying to understand the elementary basics of using a pdp-11 (learned the instruction set in college, want to revisit this), wanting to shoot some characters out the TTO/DL11 as a first program (unless that is too complicated a first program).

Running on simh. show dev has

TTO, address=17777564-17777567, vector=64

Reading docs the tx buffer is at offset 566. Seeing other code at stackoverflow and some other pages there is/might be an mmu in the upper address space that say 177566 (octal) may put you there as registers are 16 bit not 22 bits as the show dev implies.

mov $0x32,r1
movb r1, @$0177566
mov $0177566,r2
mov $0x30,r3
movb r3,(r2)
mov $0x31,r3
movb r3,(r2)
halt

and nothing comes out.

load test.bin
go

can use set console telnet=4444 and telnet to that, no change. No doubt it is something I dont get about addressing beyond 16 bits but not quite sure where to go to figure this out.

Basically I want to, unless it is a lot of code (thousands of lines of asm) to get some characters to come out of the console, I want to start there to begin to "see" something, then build on that. So if I am close but not quite or if this is not the best peripheral to start with, where to go, they all are in that upper address space.

I am using a gnu tools

pdp11-aout-as --version
GNU assembler (GNU Binutils) 2.26.20160125
Copyright (C) 2015 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or later.
This program has absolutely no warranty.
This assembler was configured for a target of `pdp11-aout'.

So the syntax is a little goofy/non-standard. The pdp11 has been supported in binutils for a few releases at least now, wanting to also take advantage of that. Binary file format for simh was not too hard to figure out, single stepping it is matching the instructions I am wanting and feeding gnu assembler.

Tried on both the apt-got v3.8-1 version of simh pdp11 as well as the github got 4.0 version, same results. using the pdp11 simulator/executable.

sim> show config
PDP-11 simulator configuration

CPU, 11/73, NOCIS, idle disabled, autoconfiguration enabled, 256KB
SYSTEM
RHA, address=17776700-17776753, vector=254
RHB, disabled
CLK, 60Hz, address=17777546-17777547, vector=100
PCLK, disabled
PTR, address=17777550-17777553, vector=70, not attached
PTP, address=17777554-17777557, vector=74, not attached
TTI, address=17777560-17777563, vector=60, 7b
TTO, address=17777564-17777567, vector=64, 7p
CR, address=17777160-17777167, vector=230, 285 cards per minute, translation 029, not attached, CR11, auto EOF, unknown format
LPT, address=17777514-17777517, vector=200, not attached
DLI, disabled
DLO, disabled
...

EDIT

#define TKS (*((volatile unsigned *)0177560))
#define TKB (*((volatile unsigned *)0177562))
#define TPS (*((volatile unsigned *)0177564))
#define TPB (*((volatile unsigned *)0177566))

void punch ( unsigned x )
{
    while((TPS&0x80)==0) continue;
    TPB=x;
}

void notmain ( void )
{
    //unsigned ra;
    //for(ra=0x30;ra<0x37;ra++) punch(ra);
    punch(0x30);
    while((TPS&0x80)==0) continue;
    return;
}

which makes

Disassembly of section .text:

00000000 <start.o>:
   0:   15c6 2000       mov $20000, sp
   4:   09f7 001a       jsr pc, 22 <_punch+0x18>
    ...

0000000a <_punch>:
   a:   1166            mov r5, -(sp)
   c:   1185            mov sp, r5
   e:   17c0 ff74       mov *$177564, r0
  12:   45c0 ff7f       bic $-201, r0
  16:   03fb            beq e <_punch+0x4>
  18:   1d5f 0004 ff76  mov 4(r5), *$177566
  1e:   1585            mov (sp)+, r5
  20:   0087            rts pc
  22:   1166            mov r5, -(sp)
  24:   1185            mov sp, r5
  26:   17c0 ff74       mov *$177564, r0
  2a:   45c0 ff7f       bic $-201, r0
  2e:   03fb            beq 26 <_punch+0x1c>
  30:   15df 0030 ff76  mov $60, *$177566
  36:   17c0 ff74       mov *$177564, r0
  3a:   45c0 ff7f       bic $-201, r0
  3e:   03fb            beq 36 <_punch+0x2c>
  40:   1585            mov (sp)+, r5
  42:   0087            rts pc

Two problems, one I was not waiting for busy. On init/reset that is okay it is not busy. I think the kicker was that I halted before it could spit the character out. When I had the loop it spit out most of the characters. If I send out one character and halt it doesnt come out, but if I put the wait for busy to go zero after (last thing in notmain()) then that character comes out.

if I change it to this

#define TKS (*((volatile unsigned *)0177560))
#define TKB (*((volatile unsigned *)0177562))
#define TPS (*((volatile unsigned *)0177564))
#define TPB (*((volatile unsigned *)0177566))

void punch ( unsigned x )
{
    TPB=x;
    while((TPS&0x80)==0) continue;
}

void notmain ( void )
{
    unsigned ra;
    for(ra=0x30;ra<0x37;ra++) punch(ra);
    return;
}

It works quite nicely...thanks for getting me kick started.

Note from a manual:

In addition to the word length constraint on basic memory addressing
space, the uppermost 4K words of address space is always reserved for
UNIBUS 1/0 device registers. In a basic PDP-11/40 memory configura·
tion (without Management) all address references to the uppermost 4K
words of 16-bit address space (170000-177777) are converted to full
18-bit reference5 with bits 17 and 16 always set to 1. Thus, a 16·bit
reference to the 1/0 device register at address 173224 is automatically
internally converted to a full 18-bit reference to the register at address
773224. Accordingly, the basic PDP-11/40 configuration can directly
address up to 28K words of true memory, and 4K words of UNIBUS 1/0
device registers.

So that answer was right there I didnt look in the right place.

EDIT2:

In assembly, to meet the goal of sending a character out the tty, using gnu assembler syntax (* instead of @ and $ instead of #)

movb $0x32,*$0177566
pwait:
   tstb *$0177564
   bpl pwait
halt

Solution

  • I think the problem is not using the DL11 correctly. You can't just give it a character any time you want to. You have to test the "ready" flag in the control register. Then, when it's ready send the character. Also, you can not reliably read back the value out of the data register. And then you are using that character as a memory pointer (there will certainly be memory down there, but writing into it probably wasn't what you intended).

    You may also be interested in looking at the Retrocomputing Stack Exchange site. I'm probably not the only one hanging out there with PDP-11 experience, but I might be here.