I'm looking over the PDP-11 CIS instruction set. Here is the listed description of the MOVTC (and MOVTCI) instruction:

MOVTC(I): Move translated character

A longer description can be found in the related text:

The MOVTC(I) instructions move a translated source string to a destination string.

Uhhh, ok.... Anyone have any details of what a "translated source string" means in this context?

  • 2
    The question demonstrates lack of research. Searching for "movtc instruction" yields documentation.help/VAX11/op_MOVTC.htm as the first result.
    – Leo B.
    Jul 8, 2022 at 22:09
  • 15
    OK, but it may not be obvious to look for a PDP-11 instruction in the VAX architecture.
    – dave
    Jul 8, 2022 at 22:19
  • 2
    It's an instruction set extension - the Commercial Instruction Set - and was available on the 11/44 and 11/24, possibly as options. I don't think it ever really took off. It's horribly unlike the rest of the ISA.
    – dave
    Jul 8, 2022 at 22:40
  • 10
    "You should have known enough to [find the] answer [to] the question yourself" does not seem like a reasonable standard to apply on a Q&A site, @LeoB... If nothing else, asking the question is a useful contribution to the knowledge base that is this Q&A site: it allows others to find the question and high-quality answers during their research. Isn't that, after all, the whole model of Q&A sites on Stack Exchange? Jul 9, 2022 at 10:13
  • 2
    @MauryMarkowitz Googling "PDP-11 movtc" does bring up the PDP-11 Processor Handbook on Bitsavers, which in turn does explain the instruction on p.391ff. GOven, it's only the third result on the first page :))
    – Raffzahn
    Jul 9, 2022 at 17:59

2 Answers 2


Anyone have any details of what a "translated source string" means in this context?

Well, that's the destination buffer (string) filled with data from a source buffer (string) like in a move, but each byte translated using a translation table before being stored.

Like having an ASCII data (source string) translated to EBCDIC (translated source string).

MOVTC works much like the /370 instruction Translate (TR). Except it not only translates a series of bytes, but also moves it to a new destination (*1).

   MOVTC  SrcLn,SrcBuffer,Filler,Table,DestLen,DestBuffer


SrcLn      - Length of data within the source buffer
SrcBuffer  - Address of source buffer
Filler     - Byte to fill the destination buffer
Table      - Translate table
DestLen    - Length of destination buffer
DestBuffer - Address on destination buffer

During operation each byte from the source buffer is used as an index into the translation table. The byte pointed to will be stored at the destination buffer. If DestLen is longer than SrcLen, the remaining destination buffer is filled with the Filler byte. If DestLen is shorter, then the operation is ended after DestLen translations.

In either case the condition code is set to reflect

  • all translated
  • DestBuffer too short
  • Filling was used.

In addition, various registers contain

  • First source byte not translated
  • Address after Destination buffer
  • Number of bytes remaining in source buffer

The Table is an up-to-256-byte structure holding the destination encoding at the address of the source encoding. For example an ASCII to EBCDIC table would have:

Table+65 = X'C1'   ;A
Table+66 = X'C2'   ;B
Table+67 = X'C3'   ;C
Table+68 = X'C4'   ;D

and so on.

Translation of byte strings is a very handy feature for code conversion, for example ASCII to EBCDIC for line code to internal, For between various line codes. In addition it's a very handy instruction to check character types and flags (*2) or for native implementation of decision tables (*3) or many other uses.

Not only has the /360 included it since the 1960s, but so has 8086 in the form of the XLAT instruction - which is part of the string instructions. A simple equivalent with source/destination length in 8086 is a loop of just 4 instructions:

    LEA   SI,SrcBuffer
    LEA   DI,DestBuffer
    LEA   BX,Table
    MOV   CX,Len
    LOOP  LP

*1 - MOVETC with source and destination at the same address would be exactly like TS. Amdahl had only two address fields, while DEC could make up as many as they wanted, so why not offer the freedom of moving at the same time.

*2 - Type checking like if a character is a letter or numeral is often done in code and is codeset dependent. The original implementation for C's isalpha as Macro looked a bit like:

#define isalpha(ch) ( (ch) <= 'Z' && (ch) >= ('A')  || ((ch) >= 'a') && ((ch) <= 'z') )

This will break with any code not having A..Z and a..z in consecutive places and/or providing additional letters - like EBCDIC or ISO8859. Now one can turn the macro into a function and make it compile differently depending on codeset, or build a sophisticated run time system selecting what checks are appropriate ... or simply keep for each code to be handled as a 256-byte table with a testable value like

  • 2^0 -> Upper
  • 2^1 -> Lower
  • 2^2 -> Numeric
  • 2^3 -> Punctuation
  • 2^4 -> Whitespace
  • 2^5 -> Control

After translating, isalpha is reduced to a test for (2^0 OR 2^1) independent of the codeset used. Even better, whole strings can be tested at once by ANDing or ORing all translated characters. When ANDed, the markers are only set where all characters have the same attribute, like numeric (2^2) is only set if all characters entered are numeric. When ORed, they are set when any of them has that attribute, like for the dreaded checking if a password contains Upper and lower and numeric and symbols.

So, VERY handy.

*3 - Decision Tables are a very handy tool to structure logic with reactions depending on arbitrary combinations of multiple input items. Code translation is a way to implement such logic native and extremely performant - at least as long as there are no more than 8 input and 8 output conditions.


From memory of the very similar VAX instruction, it's something like this (in very simplistic outline, and omitting considerations of different string lengths, and possible overlap).

for (int i = 0; i < source.length; i++)
    destination[i] = lookup_table[source[i]];

That is, we're using a 'translation table' to do code conversion.

See pages 456-457 in the 1979 PDP-11 handbook.

On the 11/44, the CIS was supported by a two-board option, the KE44-A.

  • 2
    It was smarter than that: The operation of the instruction is such that overlap of the source and destination strings does not affect the result.
    – Leo B.
    Jul 8, 2022 at 22:16
  • 2
    All it takes is to compare the start addresses. If dest < source, operate forwards, else operate backwards through the source string.
    – dave
    Jul 8, 2022 at 22:29
  • Two boards! ....
    – davidbak
    Jul 8, 2022 at 23:40
  • @LeoB. true, but not as useful as it sounds - also putting more stress on cache.
    – Raffzahn
    Jul 9, 2022 at 9:47
  • 2
    @Raffzahn True; Without much exaggeration, it may be said that CISC ISAs were too smart for their own good.
    – Leo B.
    Jul 10, 2022 at 4:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .