Work in progress! 9 year old files or so.

The file MMIX.mmS below contains macros to ease switching between stuff that goes in the text segment (code segment) and stuff that goes in the data segment. The macros were given Norwegian names at the time. I might change the name of the macros to English once all files are made available in this post.

Copyright is, unless noted otherwise:

Copyright © 2004 Trond Endrestøl <Trond.Endrestol@ximalas.info>

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 2 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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

MMIX.mmS: macros to ease switching between stuff that goes in the text segment and stuff that goes in the data segment:

#ifndef _MMIX_mmS
#define _MMIX_mmS
* VIKTIG:  _Ikke_ bruk de lokale symbolene 9 og 0 til egne formål!

9H		IS	#100
0H		IS	Data_Segment
		LOC	0B
		GREG	@

#define StartDatasegment \
0H		LOC	0B

#define AvsluttDatasegment \
0H		IS	@

#define StartKodesegment \
9H		LOC	9B

#define AvsluttKodesegment \
9H		IS	@

#define WydealignKodesegment \
9H		LOC	(@+1)&-2

#define TetraalignKodesegment \
9H		LOC	(@+3)&-4

#define OctaalignKodesegment \
9H		LOC	(@+7)&-8

#define WydealignDatasegment \
0H		LOC	(@+1)&-2

#define TetraalignDatasegment \
0H		LOC	(@+3)&-4

#define OctaalignDatasegment \
0H		LOC	(@+7)&-8

* Slutt på MMIX.mmS.
#endif

abort.mmS: MMIXAL implementation of abort():

#ifndef _abort_mmS
#define _abort_mmS
#include "MMIX.mmS"

		PREFIX	:abort:

* void abort(void);

t		IS	$255

StartKodesegment
tekst		BYTE	#0A,"!! abort trap !!",#0A,0

:abort		GETA	t,tekst			t = &tekst;
		TRAP	0,:Fputs,:StdErr	t = fputs(t, :StdErr);

		TRAP	0,:Fclose,:StdIn	t = fclose(:StdIn);
		TRAP	0,:Fclose,:StdOut	t = fclose(:StdOut);
		TRAP	0,:Fclose,:StdErr	t = fclose(:StdErr);

		SET	t,#FF			t = 0xFF;
		TRAP	0,:Halt,0		_exit(t);
AvsluttKodesegment

* Slutt på abort.mmS.
#endif

bzero.mmS: MMIXAL implementation of bzero():

#ifndef _bzero_mmS
#define _bzero_mmS
#include "memset.mmS"

		PREFIX	:bzero:

* void bzero(void *b, size_t len);

b		IS	$0
len		IS	$1
hole		IS	$2
bb		IS	$3
c		IS	$4
lenlen		IS	$5

StartKodesegment
:bzero		SET	bb,b		bb = b;
		SET	c,0		c = 0;
		SET	lenlen,len	lenlen = len;
		PUSHJ	hole,:memset	hole = :memset(bb, c, lenlen);
		POP	0,0		return;
AvsluttKodesegment

* Slutt på bzero.mmS.
#endif

errno.mmS: errno values based on FreeBSD 4.10, the operating system on my development system back in 2004:

#ifndef _errno_mmS
#define _errno_mmS
#include "MMIX.mmS"

#if 0
/*-
 * Copyright (c) 1982, 1986, 1989, 1993
 *	The Regents of the University of California.  All rights reserved.
 * (c) UNIX System Laboratories, Inc.
 * All or some portions of this file are derived from material licensed
 * to the University of California by American Telephone and Telegraph
 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
 * the permission of UNIX System Laboratories, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed by the University of
 *      California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)errno.h	8.5 (Berkeley) 1/21/94
 * $FreeBSD: release/4.10.0/sys/sys/errno.h 128520 2004-04-21 11:08:56Z cvs2svn $
 */
#endif

		PREFIX	:

errno		GREG	0

EPERM		IS	1		/* Operation not permitted */
ENOENT		IS	2		/* No such file or directory */
ESRCH		IS	3		/* No such process */
EINTR		IS	4		/* Interrupted system call */
EIO		IS	5		/* Input/output error */
ENXIO		IS	6		/* Device not configured */
E2BIG		IS	7		/* Argument list too long */
ENOEXEC		IS	8		/* Exec format error */
EBADF		IS	9		/* Bad file descriptor */
ECHILD		IS	10		/* No child processes */
EDEADLK		IS	11		/* Resource deadlock avoided */
					/* 11 was EAGAIN */
ENOMEM		IS	12		/* Cannot allocate memory */
EACCES		IS	13		/* Permission denied */
EFAULT		IS	14		/* Bad address */
ENOTBLK		IS	15		/* Block device required */
EBUSY		IS	16		/* Device busy */
EEXIST		IS	17		/* File exists */
EXDEV		IS	18		/* Cross-device link */
ENODEV		IS	19		/* Operation not supported by device */
ENOTDIR		IS	20		/* Not a directory */
EISDIR		IS	21		/* Is a directory */
EINVAL		IS	22		/* Invalid argument */
ENFILE		IS	23		/* Too many open files in system */
EMFILE		IS	24		/* Too many open files */
ENOTTY		IS	25		/* Inappropriate ioctl for device */
ETXTBSY		IS	26		/* Text file busy */
EFBIG		IS	27		/* File too large */
ENOSPC		IS	28		/* No space left on device */
ESPIPE		IS	29		/* Illegal seek */
EROFS		IS	30		/* Read-only file system */
EMLINK		IS	31		/* Too many links */
EPIPE		IS	32		/* Broken pipe */

/* math software */
EDOM		IS	33		/* Numerical argument out of domain */
ERANGE		IS	34		/* Result too large */

/* non-blocking and interrupt i/o */
EAGAIN		IS	35		/* Resource temporarily unavailable */
EWOULDBLOCK	IS	EAGAIN		/* Operation would block */
EINPROGRESS	IS	36		/* Operation now in progress */
EALREADY	IS	37		/* Operation already in progress */

/* ipc/network software -- argument errors */
ENOTSOCK	IS	38		/* Socket operation on non-socket */
EDESTADDRREQ	IS	39		/* Destination address required */
EMSGSIZE	IS	40		/* Message too long */
EPROTOTYPE	IS	41		/* Protocol wrong type for socket */
ENOPROTOOPT	IS	42		/* Protocol not available */
EPROTONOSUPPORT	IS	43		/* Protocol not supported */
ESOCKTNOSUPPORT	IS	44		/* Socket type not supported */
EOPNOTSUPP	IS	45		/* Operation not supported */
ENOTSUP		IS	EOPNOTSUPP	/* Operation not supported */
EPFNOSUPPORT	IS	46		/* Protocol family not supported */
EAFNOSUPPORT	IS	47		/* Address family not supported by protocol family */
EADDRINUSE	IS	48		/* Address already in use */
EADDRNOTAVAIL	IS	49		/* Can't assign requested address */

/* ipc/network software -- operational errors */
ENETDOWN	IS	50		/* Network is down */
ENETUNREACH	IS	51		/* Network is unreachable */
ENETRESET	IS	52		/* Network dropped connection on reset */
ECONNABORTED	IS	53		/* Software caused connection abort */
ECONNRESET	IS	54		/* Connection reset by peer */
ENOBUFS		IS	55		/* No buffer space available */
EISCONN		IS	56		/* Socket is already connected */
ENOTCONN	IS	57		/* Socket is not connected */
ESHUTDOWN	IS	58		/* Can't send after socket shutdown */
ETOOMANYREFS	IS	59		/* Too many references: can't splice */
ETIMEDOUT	IS	60		/* Operation timed out */
ECONNREFUSED	IS	61		/* Connection refused */

ELOOP		IS	62		/* Too many levels of symbolic links */
ENAMETOOLONG	IS	63		/* File name too long */

/* should be rearranged */
EHOSTDOWN	IS	64		/* Host is down */
EHOSTUNREACH	IS	65		/* No route to host */
ENOTEMPTY	IS	66		/* Directory not empty */

/* quotas & mush */
EPROCLIM	IS	67		/* Too many processes */
EUSERS		IS	68		/* Too many users */
EDQUOT		IS	69		/* Disc quota exceeded */

/* Network File System */
ESTALE		IS	70		/* Stale NFS file handle */
EREMOTE		IS	71		/* Too many levels of remote in path */
EBADRPC		IS	72		/* RPC struct is bad */
ERPCMISMATCH	IS	73		/* RPC version wrong */
EPROGUNAVAIL	IS	74		/* RPC prog. not avail */
EPROGMISMATCH	IS	75		/* Program version wrong */
EPROCUNAVAIL	IS	76		/* Bad procedure for program */

ENOLCK		IS	77		/* No locks available */
ENOSYS		IS	78		/* Function not implemented */

EFTYPE		IS	79		/* Inappropriate file type or format */
EAUTH		IS	80		/* Authentication error */
ENEEDAUTH	IS	81		/* Need authenticator */
EIDRM		IS	82		/* Identifier removed */
ENOMSG		IS	83		/* No message of desired type */
EOVERFLOW	IS	84		/* Value too large to be stored in data type */
ECANCELED	IS	85		/* Operation canceled */
EILSEQ		IS	86		/* Illegal byte sequence */
ELAST		IS	86		/* Must be equal largest errno */

* Slutt på errno.mmS.
#endif

isalnum.mmS: MMIXAL implementation of isalnum():

#ifndef _isalnum_mmS
#define _isalnum_mmS
#include "isalpha.mmS"
#include "isdigit.mmS"

		PREFIX	:isalnum:

* int isalnum(int c);

c		IS	$0
rJ		IS	$1
hole1		IS	$2
cc1		IS	$3
hole2		IS	$3
cc2		IS	$4
t		IS	$255

StartKodesegment
:isalnum	GET	rJ,:rJ		rJ = :rJ;

		SET	cc1,c		cc1 = c;
		PUSHJ	hole1,:isalpha	hole1 = :isalpha(cc1);

		SET	cc2,c		cc2 = c;
		PUSHJ	hole2,:isdigit	hole2 = :isdigit(cc2);

		PUT	:rJ,rJ		:rJ = rJ;

		OR	c,hole1,hole2	c = hole1 || hole2;
		POP	1,0		return c;
AvsluttKodesegment

* Slutt på isalnum.mmS.
#endif

isalpha.mmS: MMIXAL implementation of isalpha():

#ifndef _isalpha_mmS
#define _isalpha_mmS
#include "toupper.mmS"

		PREFIX	:isalpha:

* int isalpha(int c);

c		IS	$0
rJ		IS	$1
hole		IS	$2
cc		IS	$3
t		IS	$255

StartKodesegment
:isalpha	SET	cc,c		cc = c;
		GET	rJ,:rJ		rJ = :rJ;
		PUSHJ	hole,:toupper	hole = :toupper(cc);
		PUT	:rJ,rJ		:rJ = rJ;
		SET	c,hole		c = hole;

		CMP	t,c,'A'		if (c < 'A')
		BN	t,1F		  goto 1F;
		CMP	t,c,'Z'		if (c > 'Z')
		BP	t,1F		  goto 1F;

		SET	c,1		c = 1;
		POP	1,0		return c;

1H		SET	c,0		c = 0;
		POP	1,0		return c;
AvsluttKodesegment

* Slutt på isalpha.mmS.
#endif

isascii.mmS: MMIXAL implementation of isascii():

#ifndef _isascii_mmS
#define _isascii_mmS
#include "MMIX.mmS"

		PREFIX	:isascii:

* int isascii(int c);

c		IS	$0
t		IS	$255

StartKodesegment
:isascii	CMP	t,c,0		if (c < 0)
		BN	t,1F		  goto 1F;
		CMP	t,c,#7F		if (c > 0x7F)
		BP	t,1F		  goto 1F;

		SET	c,1		c = 1;
		POP	1,0		return c;

1H		SET	c,0		c = 0;
		POP	1,0		return c;
AvsluttKodesegment

* Slutt på isascii.mmS.
#endif

iscntrl.mmS: MMIXAL implementation of iscntrl():

#ifndef _iscntrl_mmS
#define _iscntrl_mmS
#include "MMIX.mmS"

		PREFIX	:iscntrl:

* int iscntrl(int c);

c		IS	$0
t		IS	$255

StartKodesegment
:iscntrl	CMP	t,c,#7F		if (c == 0x7F)
		BZ	t,2F		  goto 2F;
		CMP	t,c,0		if (c < 0)
		BN	t,1F		  goto 1F;
		CMP	t,c,#1F		if (c > 0x1F)
		BP	t,1F		  goto 1F;

2H		SET	c,1		c = 1;
		POP	1,0		return c;

1H		SET	c,0		c = 0;
		POP	1,0		return c;
AvsluttKodesegment

* Slutt på iscntrl.mmS.
#endif

isdigit.mmS: MMIXAL implementation of isdigit():

#ifndef _isdigit_mmS
#define _isdigit_mmS
#include "MMIX.mmS"

		PREFIX	:isdigit:

* int isdigit(int c);

c		IS	$0
t		IS	$255

StartKodesegment
:isdigit	CMP	t,c,'0'		if (c < '0')
		BN	t,1F		  goto 1F;
		CMP	t,c,'9'		if (c > '9')
		BP	t,1F		  goto 1F;

		SET	c,1		c = 1;
		POP	1,0		return c;

1H		SET	c,0		c = 0;
		POP	1,0		return c;
AvsluttKodesegment

* Slutt på isdigit.mmS.
#endif

isgraph.mmS: MMIXAL implementation of isgraph():

#ifndef _isgraph_mmS
#define _isgraph_mmS
#include "MMIX.mmS"

		PREFIX	:isgraph:

* int isgraph(int c);

c		IS	$0
t		IS	$255

StartKodesegment
:isgraph	CMP	t,c,'!'		if (c < '!')
		BN	t,1F		  goto 1F;
		CMP	t,c,'~'		if (c > '~')
		BP	t,1F		  goto 1F;

		SET	c,1		c = 1;
		POP	1,0		return c;

1H		SET	c,0		c = 0;
		POP	1,0		return c;
AvsluttKodesegment

* Slutt på isgraph.mmS.
#endif

islower.mmS: MMIXAL implementation of islower():

#ifndef _islower_mmS
#define _islower_mmS
#include "MMIX.mmS"

		PREFIX	:islower:

* int islower(int c);

c		IS	$0
t		IS	$255

StartKodesegment
:islower	CMP	t,c,'a'		if (c < 'a')
		BN	t,1F		  goto 1F;
		CMP	t,c,'z'		if (c > 'z')
		BP	t,1F		  goto 1F;

		SET	c,1		c = 1;
		POP	1,0		return c;

1H		SET	c,0		c = 0;
		POP	1,0		return c;
AvsluttKodesegment

* Slutt på islower.mmS.
#endif

isspace.mmS: MMIXAL implementation of isspace():

#ifndef _isspace_mmS
#define _isspace_mmS
#include "MMIX.mmS"

		PREFIX	:isspace:

* int isspace(int c);

c		IS	$0
t		IS	$255

StartKodesegment
:isspace	CMP	t,c,' '		if (c == ' ')
		BZ	t,1F		  goto 1F;
		CMP	t,c,#09		if (c < 0x09)
		BN	t,2F		  goto 2F;
		CMP	t,c,#0D		if (c > 0x0D)
		BP	t,2F		  goto 2F;

1H		SET	c,1		c = 1;
		POP	1,0		return c;

2H		SET	c,0		c = 0;
		POP	1,0		return c;
AvsluttKodesegment

* Slutt på isspace.mmS.
#endif

isupper.mmS: MMIXAL implementation of isupper():

#ifndef _isupper_mmS
#define _isupper_mmS
#include "MMIX.mmS"

		PREFIX	:isupper:

* int isupper(int c);

c		IS	$0
t		IS	$255

StartKodesegment
:isupper	CMP	t,c,'A'		if (c < 'A')
		BN	t,1F		  goto 1F;
		CMP	t,c,'Z'		if (c > 'Z')
		BP	t,1F		  goto 1F;

		SET	c,1		c = 1;
		POP	1,0		return c;

1H		SET	c,0		c = 0;
		POP	1,0		return c;
AvsluttKodesegment

* Slutt på isupper.mmS.
#endif

memset.mmS: MMIXAL implementation of memset():

#ifndef _memset_mmS
#define _memset_mmS
#include "MMIX.mmS"

		PREFIX	:memset:

* void *memset(void *b, int c, size_t len);

b		IS	$0
c		IS	$1
len		IS	$2
t		IS	$255

StartKodesegment
1H		STBU	c,t		*t = c;
		ADDU	t,t,1		t++;
		SUBU	len,len,1	len--;
1H		PBNZ	len,1B		if (len != 0) goto 1B;
		POP	1,0		return b;
:memset		SET	t,b		t = b;
		JMP	1B		goto 1B;
AvsluttKodesegment

* Slutt på memset.mmS.
#endif

perror.mmS: MMIXAL implementation of perror():

#ifndef _perror_mmS
#define _perror_mmS
#include "errno.mmS"
#include "sys_errlist.mmS"
#include "printX.mmS"

		PREFIX	:perror:

* void perror(const char *string);

string		IS	$0
errno		IS	$1
rJ		IS	$2
hole		IS	$3
n		IS	$4
b		IS	$5
t		IS	$255

StartKodesegment
colonspace	BYTE	": ",0
TetraalignKodesegment
newline		BYTE	#0A,0

:perror		BZ	string,1F		if (string == 0) goto 1F;
		LDBU	t,string		t = *string;
		BZ	t,1F			if (t == 0) goto 1F;

		SET	t,string		t = string;
		TRAP	0,:Fputs,:StdErr	t = fputs(t, stderr);
		GETA	t,colonspace		t = &colonspace;
		TRAP	0,:Fputs,:StdErr	t = fputs(t, stderr);

1H		SET	errno,:errno		errno = :errno;
		CMPU	t,errno,:ELAST		if (errno <= :ELAST)
		PBNP	t,2F			  goto 2F;
		SET	errno,:ELAST+2		errno = :ELAST + 2;

2H		GETA	t,:sys_errlist		t = &:sys_errlist;
		8ADDU	t,errno,t		t += 8 * errno;
		LDOU	t,t			t = *t
		TRAP	0,:Fputs,:StdErr	t = fputs(t, stderr);

		BZ	:errno,1F		if (:errno == 0) goto 1F;
		CMPU	t,:errno,:ELAST		if (:errno > :ELAST)
		BP	t,1F			  goto 1F;
		JMP	2F			goto 2F;

1H		GETA	t,colonspace		t = &colonspace;
		TRAP	0,:Fputs,:StdErr	t = fputs(t, stderr);
		SET	n,:errno		n = :errno;
		SET	b,10			b = 10;
		GET	rJ,:rJ			rJ = :rJ;
		PUSHJ	hole,:printX		hole = printX(n, b);
		PUT	:rJ,rJ			:rJ = rJ;

2H		GETA	t,newline		t = &newline;
		TRAP	0,:Fputs,:StdErr	t = fputs(t, stderr);
		POP	0,0			return;
AvsluttKodesegment

* Slutt på perror.mmS.
#endif

printX.mmS: MMIXAL implementation of printX():

#ifndef _printX_mmS
#define _printX_mmS
#include "MMIX.mmS"

		PREFIX	:printX:

* unsigned long long printX(unsigned long long n, unsigned long long b)

n		IS	$0
b		IS	$1
nmodb		IS	$2
rJ		IS	$3
hole		IS	$4
ndivb		IS	$5
bb		IS	$6
t		IS	$255

StartDatasegment
OctaalignDatasegment
		GREG	@
digit		BYTE	0,0
AvsluttDatasegment

StartKodesegment
:printX		CMPU	t,b,10			if (b == 10)
		PBZ	t,1F			  goto 1F;
		CMPU	t,b,16			if (b == 16)
		PBZ	t,1F			  goto 1F;
		CMPU	t,b,8			if (b ==  8)
		PBZ	t,1F			  goto 1F;
		CMPU	t,b,2			if (b ==  2)
		PBZ	t,1F			  goto 1F;

		SET	n,0			n = 0;
		POP	1,0			return n;

1H		DIVU	ndivb,n,b		ndivb = n / b;
		GET	nmodb,:rR		nmodb = n % b;

		BZ	ndivb,1F		if (ndivb == 0) goto 1F;

		SET	bb,b			bb = b;
		GET	rJ,:rJ			rJ = :rJ;
		PUSHJ	hole,1B			1B(ndivb, bb);
		PUT	:rJ,rJ			:rJ = rJ;

1H		CMPU	t,nmodb,9		if (nmodb > 9)
		BP	t,1F			  goto 1F;

		ADDU	nmodb,nmodb,'0'		nmodb += '0';
		JMP	2F			goto 2F;

1H		SUBU	nmodb,nmodb,10		nmodb -= 10;
		ADDU	nmodb,nmodb,'A'		nmodb += 'A';

2H		STBU	nmodb,digit		*digit = (char)nmodb;
		LDA	t,digit			t = &digit;
		TRAP	0,:Fputs,:StdOut	fputs(t, stdout);

		SET	n,1			n = 1;
		POP	1,0			return n;
AvsluttKodesegment

* Slutt på printX.mmS.
#endif

rc4.mmS: MMIXAL implementation of ARC4:

#ifndef _rc4_mmS
#define _rc4_mmS
#include "MMIX.mmS"

		PREFIX	:rc4:

StartDatasegment
OctaalignDatasegment
		GREG	@
ii		OCTA	0
jj		OCTA	0
S		IS	@
		LOC	@+256
		GREG	@
AvsluttDatasegment

StartKodesegment
		PREFIX	:rc4:keyinit:

* void keyinit(unsigned char *K, size_t n);

K		IS	$0
n		IS	$1
i		IS	$2
tofemseks	IS	$3
p		IS	$4
j		IS	$5
k		IS	$6
Si		IS	$7
Sj		IS	$8
Kk		IS	$9
t		IS	$255

:rc4:keyinit	SETL	tofemseks,#0100		tofemseks = 0x0100;
		LDA	p,:rc4:S		p = &:rc4:S;
1H		STBU	i,p,i			*(p + i) = (unsigned char)i;
		ADDU	i,i,1			i++;
		CMPU	t,i,tofemseks		if (i != tofemseks)
		PBNZ	t,1B			  goto 1B;
		SET	i,0			i = 0;
1H		DIVU	k,i,n			k = i / n, :rR = i % n;
		GET	k,:rR			k = :rR;
		LDBU	Si,p,i			Si = (unsigned char)*(p + i);
		LDBU	Kk,K,k			Kk = (unsigned char)K[k];
		ADDU	j,j,Si			j += Si;
		ADDU	j,j,Kk			j += Kk;
		DIVU	j,j,tofemseks		j /= tofemseks, :rR = j % tofemseks;
		GET	j,:rR			j = :rR;
		LDBU	Sj,p,j			Sj = (unsigned char)*(p + j);
		STBU	Si,p,j			*(p + I) = (unsigned char)Sj;
		STBU	Sj,p,i			*(p + j) = (unsigned char)Si;
		ADDU	i,i,1			i++;
		CMPU	t,i,tofemseks		if (i != tofemseks)
		PBNZ	t,1B			  goto 1B;
		SET	t,0			t = 0;
		LDA	p,:rc4:ii		p = ⅈ
		STBU	t,p			*p = (unsigned char)t;
		LDA	p,:rc4:jj		p = &jj;
		STBU	t,p			*p = (unsigned char)t;
		POP	0,0			return;

		PREFIX	:rc4:transform:

* void transform(unsigned char *B, size_t n);

B		IS	$0
n		IS	$1
p		IS	$2
i		IS	$3
j		IS	$4
tofemseks	IS	$5
Si		IS	$6
Sj		IS	$7
bb		IS	$8
t		IS	$255

1H		ADDU	i,i,1			i++;
		DIVU	i,i,tofemseks		i /= tofemseks, :rR = i % tofemseks;
		GET	i,:rR			i = :rR;
		LDBU	Si,p,i			Si = (unsigned char)*(p + i);
		ADDU	j,j,Si			j += Si;
		DIVU	j,j,tofemseks		j /= tofemseks, :rR = j % tofemseks;
		GET	j,:rR			j = :rR;
		LDBU	Sj,p,j			Sj = (unsigned char)*(p + j);
		STBU	Si,p,j			*(p + j) = (unsigned char)Si;
		STBU	Sj,p,i			*(p + i) = (unsigned char)Sj;
		ADDU	t,Si,Sj			t = Si + Sj;
		DIVU	t,t,tofemseks		t /= tofemseks, :rR = t % tofemseks;
		GET	t,:rR			t = :rR;
		LDBU	t,p,t			t = (unsigned char)*(p + t);
		LDBU	bb,B			bb = (unsigned char)*B;
		XOR	bb,bb,t			bb ^= t;
		STBU	bb,B			*B = (unsigned char)bb;
		ADDU	B,B,1			B++;
		SUBU	n,n,1			n--;
1H		PBNZ	n,1B			if (n != 0) goto 1B;
		LDA	p,:rc4:ii		p = &:rc4:ii;
		STBU	i,p			*p = (unsigned char)i;
		LDA	p,:rc4:jj		p = &:rc4:jj;
		STBU	j,p			*p = (unsigned char)j;
		SET	t,0			t = 0;
		POP	0,0			return;
:rc4:transform	LDA	p,:rc4:ii		p = &:rc4:ii;
		LDBU	i,p			i = (unsigned char)*p;
		LDA	p,:rc4:jj		p = &:rc4:jj;
		LDBU	j,p			j = (unsigned char)*p;
		LDA	p,:rc4:S		p = &:rc4:S;
		SETL	tofemseks,#0100		tofemseks = 0x0100;
		JMP	1B			goto 1B;

AvsluttKodesegment

* Slutt på rc4.mmS.
#endif

rotate.mmS: MMIXAL implementations of rotl() and rotr():

#ifndef _rotate_mmS
#define _rotate_mmS
#include "MMIX.mmS"

		PREFIX	:rotate:

* unsigned long long rotl(unsigned long long x, unsigned long long n, unsigned long long w);
* unsigned long long rotr(unsigned long long x, unsigned long long n, unsigned long long w);

x		IS	$0
n		IS	$1
w		IS	$2

StartKodesegment
:rotl		SUBU	w,w,n		w -= n;
		SRU	w,x,w		w = x >> w;
		SLU	x,x,n		x <<= n;
		OR	x,x,w		x |= w;
		POP	1,0		return x;

:rotr		SUBU	w,w,n		w -= n;
		SLU	w,x,w		w = x << w;
		SRU	x,x,n		x >>= n;
		OR	x,x,w		x |= w;
		POP	1,0		return x;
AvsluttKodesegment

* Slutt på rotate.mmS.
#endif

strchr.mmS: MMIXAL implementation of strchr():

#ifndef _strchr_mmS
#define _strchr_mmS
#include "MMIX.mmS"

		PREFIX	:strchr:

* char *strchr(const char *p, int c);

p		IS	$0
c		IS	$1
cc		IS	$2
t		IS	$255

StartKodesegment
1H		ADDU	p,p,1		p++;
:strchr		LDBU	cc,p		cc = *p;
		CMPU	t,cc,c		if (cc == c)
		BZ	t,1F		  goto 1F;
		BNZ	cc,1B		if (cc != 0) goto 1B;
		SET	p,0		p = 0;
1H		POP	1,0		return p;
AvsluttKodesegment

* Slutt på strchr.mmS.
#endif

strcpy.mmS: MMIXAL implementation of strcpy():

#ifndef _strcpy_mmS
#define _strcpy_mmS
#include "MMIX.mmS"

		PREFIX	:strcpy:

* char *strcpy(char *s1, const char *s2);

s1		IS	$0
s2		IS	$1
s3		IS	$2
t		IS	$255

StartKodesegment
2H		ADDU	s3,s3,1		s3++;
		ADDU	s2,s2,1		s2++;
1H		LDBU	t,s2		t = *s2;
		STBU	t,s3		*s3 = t;
		PBNZ	t,2B		if (t != 0) goto 2B;
		POP	1,0		return s1;
:strcpy		SET	s3,s1		s3 = s1;
		JMP	1B		goto 1B;
AvsluttKodesegment

* Slutt på strcpy.mmS.
#endif

strerror.mmS: MMIXAL implementation of strerror():

#ifndef _strerror_mmS
#define _strerror_mmS
#include "errno.mmS"
#include "sys_errlist.mmS"

		PREFIX	:strerror:

* const char *strerror(int errnum);

errnum		IS	$0
t		IS	$255

StartKodesegment
:strerror	GETA	t,:sys_errlist		t = &:sys_errlist;
		8ADDU	errnum,errnum,t		errnum = 8 * errnum + t;
		LDOU	errnum,errnum		errnum = *errnum;
		POP	1,0			return errnum;
AvsluttKodesegment

* Slutt på strerror.mmS.
#endif

strlen.mmS: MMIXAL implementation of strlen():

#ifndef _strlen_mmS
#define _strlen_mmS
#include "MMIX.mmS"

		PREFIX	:strlen:

* unsigned long long strlen(const char *p);

p		IS	$0
pp		IS	$1
t		IS	$255

StartKodesegment
2H		ADDU	pp,pp,1		pp++;
1H		LDBU	t,pp		t = *pp;
		PBNZ	t,2B		if (t != 0) goto 2B;
		SUBU	p,pp,p		p = pp - p;
		POP	1,0		return p;
:strlen		SET	pp,p		pp = p;
		JMP	1B		goto 1B;
AvsluttKodesegment

* Slutt på strlen.mmS.
#endif

strncpy.mmS: MMIXAL implementation of strncpy():

#ifndef _strncpy_mmS
#define _strncpy_mmS
#include "MMIX.mmS"

		PREFIX	:strncpy:

* char *strncpy(char *s1, const char *s2, unsigned long long len);

s1		IS	$0
s2		IS	$1
len		IS	$2
s3		IS	$3
t		IS	$255

StartKodesegment
:strncpy	SET	s3,s1		s3 = s1;
		JMP	1F		goto 1F;
2H		ADDU	s3,s3,1		s3++;
		ADDU	s2,s2,1		s2++;
		SUBU	len,len,1	len--;
1H		BZ	len,1F		if (len == 0) goto 1F;
		LDBU	t,s2		t = *s2;
		STBU	t,s3		*s3 = t;
		PBNZ	t,2B		if (t != 0) goto 2B;
1H		POP	1,0		return s1;
AvsluttKodesegment

* Slutt på strncpy.mmS.
#endif

strrchr.mmS: MMIXAL implementation of strrchr():

#ifndef _strrchr_mmS
#define _strrchr_mmS
#include "strlen.mmS"

		PREFIX	:strrchr:

* char *strrchr(const char *p, int c);

p		IS	$0
c		IS	$1
rJ		IS	$2
len		IS	$3
pp		IS	$4
ppp		IS	$2
cc		IS	$3
t		IS	$255

StartKodesegment
:strrchr	SET	pp,p		pp = p;
		GET	rJ,:rJ		rJ = :rJ;
		PUSHJ	len,:strlen	len = :strlen(pp);
		PUT	:rJ,rJ		:rJ = rJ;
		SET	ppp,p		ppp = p;
		ADDU	p,p,len		p += len;
		JMP	1F		goto 1F;

3H		CMPU	t,p,ppp		if (p < ppp)
		BN	t,4F		  goto 4F;
1H		LDBU	cc,p		cc = *p;
		CMPU	t,cc,c		if (cc == c)
		BZ	t,2F		  goto 2F;
		SUBU	p,p,1		p--;
		JMP	3B		goto 3B;

4H		SET	p,0		p = 0;
2H		POP	1,0		return p;
AvsluttKodesegment

* Slutt på strrchr.mmS.
#endif

strstr.mmS: MMIXAL implementation of strstr():

#ifndef _strstr_mmS
#define _strstr_mmS
#include "MMIX.mmS"

		PREFIX	:strstr:

* char *strstr(const char *big, const char *little);

big		IS	$0
little		IS	$1
cl		IS	$2
cb		IS	$3
big2		IS	$4
i		IS	$5
t		IS	$255

StartKodesegment
:strstr		LDBU	cl,little	cl = *little;
		PBNZ	cl,1F		if (cl != 0) goto 1F;
		POP	1,0		return big;

1H		LDBU	cb,big		cb = *big;
		CMPU	t,cb,cl		if (cb == cl)
		BZ	t,2F		  goto 2F;
		BZ	cb,6F		if (cb == 0) goto 6F;
		ADDU	big,big,1	big++;
		JMP	1B		goto 1B;

2H		ADDU	big2,big,1	big2 = big + 1;
		SET	i,1		i = 1;

4H		LDBU	cb,big2		cb = *big2;
		LDBU	cl,little,i	cl = little[i];
		CMPU	t,cb,cl		if (cb != cl)
		BNZ	t,3F		  goto 3F;
		ADDU	i,i,1		i++;
		LDBU	cl,little,i	cl = little[i];
		BZ	cl,7F		if (cl == 0) goto 7F;
		ADDU	big2,big2,1	big2++;
		JMP	4B		goto 4B;

3H		LDBU	cb,big2		cb = *big2;
		BZ	cb,6F		if (cb == 0) goto 6F;
		SET	big,big2	big = big2;
		LDBU	cl,little	cl = *little;
		JMP	1B		goto 1B;

6H		SET	big,0		big = 0;
7H		POP	1,0		return big;
AvsluttKodesegment

* Slutt på strstr.mmS.
#endif

sys_errlist.mmS: MMIXAL implementation of sys_errlist[] based on FreeBSD 4.10, the operating system on my development system back in 2004:

#ifndef _sys_errlist_mmS
#define _sys_errlist_mmS
#include "MMIX.mmS"

#if 0
/*-
 * Copyright (c) 1982, 1986, 1989, 1993
 *	The Regents of the University of California.  All rights reserved.
 * (c) UNIX System Laboratories, Inc.
 * All or some portions of this file are derived from material licensed
 * to the University of California by American Telephone and Telegraph
 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
 * the permission of UNIX System Laboratories, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed by the University of
 *      California, Berkeley and its contributors.
 * 4. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 *	@(#)errno.h	8.5 (Berkeley) 1/21/94
 * $FreeBSD: release/4.10.0/sys/sys/errno.h 128520 2004-04-21 11:08:56Z cvs2svn $
 */
#endif

		PREFIX	:sys_errlist:

StartKodesegment
ENOERR		BYTE	"Undefined error",0
TetraalignKodesegment
EPERM		BYTE	"Operation not permitted",0
TetraalignKodesegment
ENOENT		BYTE	"No such file or directory",0
TetraalignKodesegment
ESRCH		BYTE	"No such process",0
TetraalignKodesegment
EINTR		BYTE	"Interrupted system call",0
TetraalignKodesegment
EIO		BYTE	"Input/output error",0
TetraalignKodesegment
ENXIO		BYTE	"Device not configured",0
TetraalignKodesegment
E2BIG		BYTE	"Argument list too long",0
TetraalignKodesegment
ENOEXEC		BYTE	"Exec format error",0
TetraalignKodesegment
EBADF		BYTE	"Bad file descriptor",0
TetraalignKodesegment
ECHILD		BYTE	"No child processes",0
TetraalignKodesegment
EDEADLK		BYTE	"Resource deadlock avoided",0
TetraalignKodesegment
ENOMEM		BYTE	"Cannot allocate memory",0
TetraalignKodesegment
EACCES		BYTE	"Permission denied",0
TetraalignKodesegment
EFAULT		BYTE	"Bad address",0
TetraalignKodesegment
ENOTBLK		BYTE	"Block device required",0
TetraalignKodesegment
EBUSY		BYTE	"Device busy",0
TetraalignKodesegment
EEXIST		BYTE	"File exists",0
TetraalignKodesegment
EXDEV		BYTE	"Cross-device link",0
TetraalignKodesegment
ENODEV		BYTE	"Operation not supported by device",0
TetraalignKodesegment
ENOTDIR		BYTE	"Not a directory",0
TetraalignKodesegment
EISDIR		BYTE	"Is a directory",0
TetraalignKodesegment
EINVAL		BYTE	"Invalid argument",0
TetraalignKodesegment
ENFILE		BYTE	"Too many open files in system",0
TetraalignKodesegment
EMFILE		BYTE	"Too many open files",0
TetraalignKodesegment
ENOTTY		BYTE	"Inappropriate ioctl for device",0
TetraalignKodesegment
ETXTBSY		BYTE	"Text file busy",0
TetraalignKodesegment
EFBIG		BYTE	"File too large",0
TetraalignKodesegment
ENOSPC		BYTE	"No space left on device",0
TetraalignKodesegment
ESPIPE		BYTE	"Illegal seek",0
TetraalignKodesegment
EROFS		BYTE	"Read-only file system",0
TetraalignKodesegment
EMLINK		BYTE	"Too many links",0
TetraalignKodesegment
EPIPE		BYTE	"Broken pipe",0
TetraalignKodesegment
EDOM		BYTE	"Numerical argument out of domain",0
TetraalignKodesegment
ERANGE		BYTE	"Result too large",0
TetraalignKodesegment
EAGAIN		BYTE	"Resource temporarily unavailable",0
TetraalignKodesegment
EWOULDBLOCK	BYTE	"Operation would block",0
TetraalignKodesegment
EINPROGRESS	BYTE	"Operation now in progress",0
TetraalignKodesegment
EALREADY	BYTE	"Operation already in progress",0
TetraalignKodesegment
ENOTSOCK	BYTE	"Socket operation on non-socket",0
TetraalignKodesegment
EDESTADDRREQ	BYTE	"Destination address required",0
TetraalignKodesegment
EMSGSIZE	BYTE	"Message too long",0
TetraalignKodesegment
EPROTOTYPE	BYTE	"Protocol wrong type for socket",0
TetraalignKodesegment
ENOPROTOOPT	BYTE	"Protocol not available",0
TetraalignKodesegment
EPROTONOSUPPORT	BYTE	"Protocol not supported",0
TetraalignKodesegment
ESOCKTNOSUPPORT	BYTE	"Socket type not supported",0
TetraalignKodesegment
EOPNOTSUPP	BYTE	"Operation not supported",0
TetraalignKodesegment
EPFNOSUPPORT	BYTE	"Protocol family not supported",0
TetraalignKodesegment
EAFNOSUPPORT	BYTE	"Address family not supported by protocol family",0
TetraalignKodesegment
EADDRINUSE	BYTE	"Address already in use",0
TetraalignKodesegment
EADDRNOTAVAIL	BYTE	"Can't assign requested address",0
TetraalignKodesegment
ENETDOWN	BYTE	"Network is down",0
TetraalignKodesegment
ENETUNREACH	BYTE	"Network is unreachable",0
TetraalignKodesegment
ENETRESET	BYTE	"Network dropped connection on reset",0
TetraalignKodesegment
ECONNABORTED	BYTE	"Software caused connection abort",0
TetraalignKodesegment
ECONNRESET	BYTE	"Connection reset by peer",0
TetraalignKodesegment
ENOBUFS		BYTE	"No buffer space available",0
TetraalignKodesegment
EISCONN		BYTE	"Socket is already connected",0
TetraalignKodesegment
ENOTCONN	BYTE	"Socket is not connected",0
TetraalignKodesegment
ESHUTDOWN	BYTE	"Can't send after socket shutdown",0
TetraalignKodesegment
ETOOMANYREFS	BYTE	"Too many references: can't splice",0
TetraalignKodesegment
ETIMEDOUT	BYTE	"Operation timed out",0
TetraalignKodesegment
ECONNREFUSED	BYTE	"Connection refused",0
TetraalignKodesegment
ELOOP		BYTE	"Too many levels of symbolic links",0
TetraalignKodesegment
ENAMETOOLONG	BYTE	"File name too long",0
TetraalignKodesegment
EHOSTDOWN	BYTE	"Host is down",0
TetraalignKodesegment
EHOSTUNREACH	BYTE	"No route to host",0
TetraalignKodesegment
ENOTEMPTY	BYTE	"Directory not empty",0
TetraalignKodesegment
EPROCLIM	BYTE	"Too many processes",0
TetraalignKodesegment
EUSERS		BYTE	"Too many users",0
TetraalignKodesegment
EDQUOT		BYTE	"Disc quota exceeded",0
TetraalignKodesegment
ESTALE		BYTE	"Stale NFS file handle",0
TetraalignKodesegment
EREMOTE		BYTE	"Too many levels of remote in path",0
TetraalignKodesegment
EBADRPC		BYTE	"RPC struct is bad",0
TetraalignKodesegment
ERPCMISMATCH	BYTE	"RPC version wrong",0
TetraalignKodesegment
EPROGUNAVAIL	BYTE	"RPC prog. not avail",0
TetraalignKodesegment
EPROGMISMATCH	BYTE	"Program version wrong",0
TetraalignKodesegment
EPROCUNAVAIL	BYTE	"Bad procedure for program",0
TetraalignKodesegment
ENOLCK		BYTE	"No locks available",0
TetraalignKodesegment
ENOSYS		BYTE	"Function not implemented",0
TetraalignKodesegment
EFTYPE		BYTE	"Inappropriate file type or format",0
TetraalignKodesegment
EAUTH		BYTE	"Authentication error",0
TetraalignKodesegment
ENEEDAUTH	BYTE	"Need authenticator",0
TetraalignKodesegment
EIDRM		BYTE	"Identifier removed",0
TetraalignKodesegment
ENOMSG		BYTE	"No message of desired type",0
TetraalignKodesegment
EOVERFLOW	BYTE	"Value too large to be stored in data type",0
TetraalignKodesegment
ECANCELED	BYTE	"Operation canceled",0
TetraalignKodesegment
EILSEQ		BYTE	"Illegal byte sequence",0
TetraalignKodesegment
EERR		BYTE	"Unknown error",0

:sys_errlist	OCTA	ENOERR
		OCTA	EPERM
		OCTA	ENOENT
		OCTA	ESRCH
		OCTA	EINTR
		OCTA	EIO
		OCTA	ENXIO
		OCTA	E2BIG
		OCTA	ENOEXEC
		OCTA	EBADF
		OCTA	ECHILD
		OCTA	EDEADLK
		OCTA	ENOMEM
		OCTA	EACCES
		OCTA	EFAULT
		OCTA	ENOTBLK
		OCTA	EBUSY
		OCTA	EEXIST
		OCTA	EXDEV
		OCTA	ENODEV
		OCTA	ENOTDIR
		OCTA	EISDIR
		OCTA	EINVAL
		OCTA	ENFILE
		OCTA	EMFILE
		OCTA	ENOTTY
		OCTA	ETXTBSY
		OCTA	EFBIG
		OCTA	ENOSPC
		OCTA	ESPIPE
		OCTA	EROFS
		OCTA	EMLINK
		OCTA	EPIPE
		OCTA	EDOM
		OCTA	ERANGE
		OCTA	EAGAIN
		OCTA	EWOULDBLOCK
		OCTA	EINPROGRESS
		OCTA	EALREADY
		OCTA	ENOTSOCK
		OCTA	EDESTADDRREQ
		OCTA	EMSGSIZE
		OCTA	EPROTOTYPE
		OCTA	ENOPROTOOPT
		OCTA	EPROTONOSUPPORT
		OCTA	ESOCKTNOSUPPORT
		OCTA	EOPNOTSUPP
		OCTA	EPFNOSUPPORT
		OCTA	EAFNOSUPPORT
		OCTA	EADDRINUSE
		OCTA	EADDRNOTAVAIL
		OCTA	ENETDOWN
		OCTA	ENETUNREACH
		OCTA	ENETRESET
		OCTA	ECONNABORTED
		OCTA	ECONNRESET
		OCTA	ENOBUFS
		OCTA	EISCONN
		OCTA	ENOTCONN
		OCTA	ESHUTDOWN
		OCTA	ETOOMANYREFS
		OCTA	ETIMEDOUT
		OCTA	ECONNREFUSED
		OCTA	ELOOP
		OCTA	ENAMETOOLONG
		OCTA	EHOSTDOWN
		OCTA	EHOSTUNREACH
		OCTA	ENOTEMPTY
		OCTA	EPROCLIM
		OCTA	EUSERS
		OCTA	EDQUOT
		OCTA	ESTALE
		OCTA	EREMOTE
		OCTA	EBADRPC
		OCTA	ERPCMISMATCH
		OCTA	EPROGUNAVAIL
		OCTA	EPROGMISMATCH
		OCTA	EPROCUNAVAIL
		OCTA	ENOLCK
		OCTA	ENOSYS
		OCTA	EFTYPE
		OCTA	EAUTH
		OCTA	ENEEDAUTH
		OCTA	EIDRM
		OCTA	ENOMSG
		OCTA	EOVERFLOW
		OCTA	ECANCELED
		OCTA	EILSEQ
		OCTA	EERR
		OCTA	0
AvsluttKodesegment

* Slutt på sys_errlist.mmS.
#endif

tolower.mmS: MMIXAL implementation of tolower():

#ifndef _tolower_mmS
#define _tolower_mmS
#include "MMIX.mmS"

		PREFIX	:tolower:

* int tolower(int c);

c		IS	$0
t		IS	$255

StartKodesegment
:tolower	CMPU	t,c,'A'		if (c < 'A')
		BN	t,1F		  goto 1F;
		CMPU	t,c,'Z'		if (c > 'Z')
		BP	t,1F		  goto 1F;

		ADDU	c,c,'a'-'A'	c += 'a' - 'A';
1H		POP	1,0		return c;
AvsluttKodesegment

* Slutt på tolower.mmS.
#endif

toupper.mmS: MMIXAL implementation of toupper():

#ifndef _toupper_mmS
#define _toupper_mmS
#include "MMIX.mmS"

		PREFIX	:toupper:

* int toupper(int c);

c		IS	$0
t		IS	$255

StartKodesegment
:toupper	CMPU	t,c,'a'		if (c < 'a')
		BN	t,1F		  goto 1F;
		CMPU	t,c,'z'		if (c > 'z')
		BP	t,1F		  goto 1F;

		SUBU	c,c,'a'-'A'	c -= 'a' - 'A';
1H		POP	1,0		return c;
AvsluttKodesegment

* Slutt på toupper.mmS.
#endif

Here's a small test program for the above code. It seems I was trying to test an unpublished malloc() implementation. I might revisit that implementation someday (and maybe even publish it once I get it working correctly).

#include "abort.mmS"
#include "bzero.mmS"
#include "errno.mmS"
#include "isalnum.mmS"
#include "isalpha.mmS"
#include "isascii.mmS"
#include "iscntrl.mmS"
#include "isdigit.mmS"
#include "isgraph.mmS"
#include "islower.mmS"
#include "isspace.mmS"
#include "isupper.mmS"
#include "malloc.mmS"
#include "memset.mmS"
#include "perror.mmS"
#include "printX.mmS"
#include "rc4.mmS"
#include "rotate.mmS"
#include "strchr.mmS"
#include "strcpy.mmS"
#include "strlen.mmS"
#include "strncpy.mmS"
#include "strrchr.mmS"
#include "strstr.mmS"
#include "tolower.mmS"
#include "toupper.mmS"

		PREFIX	:Main:

* StartDatasegment
* OctaalignDatasegment
* buffer		LOC	@+1024
* bufferslutt	IS	@
* bufferlengde	IS	bufferslutt-buffer
* 		GREG	@
* rc4key		BYTE	"Dette er nøkkelen!",0
* rc4buffer	BYTE	"Denne teksten skal krypteres med RC4!",#0A,0
* AvsluttDatasegment

* int main(int argc, char **argv);

argc		IS	$0
argv		IS	$1

* len		IS	$2
* p		IS	$3

* hole		IS	$3
* s1		IS	$4
* s2		IS	$5

* len2		IS	$6

* n		IS	$4
* b		IS	$5

* rc4hole		IS	$2
* rc4arg1		IS	$3
* rc4arg2		IS	$4

len		IS	$2

p1		IS	$3
size1		IS	$4

p2		IS	$4
size2		IS	$5

t		IS	$255

StartKodesegment
* tekst		BYTE	"Hei på deg, din gamle sei!",#0A,0

* TetraalignKodesegment
* big		BYTE	"En lang tekststreng med mange ord",0

* TetraalignKodesegment
* little		BYTE	"man",0

* TetraalignKodesegment
* newline		BYTE	#0A,0

:Main		SWYM

*		GETA	p,tekst			Beregne lengden av tekst.
*		PUSHJ	len,:strlen

*		LDA	s1,buffer		Kopiere tekst til buffer.
*		GETA	s2,tekst
*		ADDU	len2,len,1
*		PUSHJ	hole,:strncpy

*		LDA	t,buffer		Skrive ut buffer på StdOut.
*		TRAP	0,:Fputs,:StdOut

*		SET	n,2009			Skrive ut 2009 desimalt.
*		SET	b,10
*		PUSHJ	hole,:printX
*		GETA	t,newline		Skrive ut et linjeskift.
*		TRAP	0,:Fputs,:StdOut

*		SET	n,2009			Skrive ut 2009 heksadesimalt.
*		SET	b,16
*		PUSHJ	hole,:printX
*		GETA	t,newline		Skrive ut et linjeskift.
*		TRAP	0,:Fputs,:StdOut

*		SET	n,2009			Skrive ut 2009 binært.
*		SET	b,2
*		PUSHJ	hole,:printX
*		GETA	t,newline		Skrive ut et linjeskift.
*		TRAP	0,:Fputs,:StdOut

*		GETA	s1,big			Søke etter substreng.
*		GETA	s2,little
*		PUSHJ	hole,:strstr

*		GETA	s1,big			Skrive ut en feilmelding.
*		PUSHJ	hole,:perror

*		SET	:errno,34
*		GETA	s1,big
*		PUSHJ	hole,:perror

*		SET	:errno,2009
*		GETA	s1,big
*		PUSHJ	hole,:perror

*		PUSHJ	hole,:abort		Teste abort().

* Først skrive ut teksten og kryptere den:
* 		LDA	t,rc4buffer
* 		TRAP	0,:Fputs,:StdOut

* 		LDA	rc4arg1,rc4key
* 		PUSHJ	rc4hole,:strlen
* 		SET	rc4arg2,rc4hole
* 		LDA	rc4arg1,rc4key
* 		PUSHJ	rc4hole,:rc4:keyinit

* 		LDA	rc4arg1,rc4buffer
* 		PUSHJ	rc4hole,:strlen
* 		SUBU	rc4arg2,rc4hole,1
* 		LDA	rc4arg1,rc4buffer
* 		PUSHJ	rc4hole,:rc4:transform

* Ta sjansen på å skrive ut kryptoteksten:
* 		LDA	t,rc4buffer
* 		TRAP	0,:Fputs,:StdOut

* Deretter dekryptere den og skrive den ut:
* 		LDA	rc4arg1,rc4key
* 		PUSHJ	rc4hole,:strlen
* 		SET	rc4arg2,rc4hole
* 		LDA	rc4arg1,rc4key
* 		PUSHJ	rc4hole,:rc4:keyinit

* 		LDA	rc4arg1,rc4buffer
* 		PUSHJ	rc4hole,:strlen
* 		SUBU	rc4arg2,rc4hole,1
* 		LDA	rc4arg1,rc4buffer
* 		PUSHJ	rc4hole,:rc4:transform

* 		LDA	t,rc4buffer
* 		TRAP	0,:Fputs,:StdOut

		SET	size1,1800
		PUSHJ	p1,:malloc

		SETH	size2,#2000
		PUSHJ	p2,:malloc

		SET	t,0			t = 0;
		TRAP	0,:Halt,0		_exit(t);
AvsluttKodesegment

* Slutt på main.mmS.

Finally, here's a GNUmakefile driving the assembler:

# GNU Makefile for forhåndsbehandling av MMIX assemblykode.
#
# Copyright © 2004 Trond Endrestøl <Trond.Endrestol@ximalas.info>
#
# 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 2 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, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
CPP=		cpp
MMIXAL=		mmixal
MMIX=		mmix
RM=		rm

%.mms: %.mmS GNUmakefile
	$(CPP) -nostdinc - - < $< > $@

%.mmo: %.mms GNUmakefile
	$(MMIXAL) -l $(basename $<).mml -b 1024 $<

%.mmb: %.mmo GNUmakefile
	$(MMIX) -D$(basename $>).mmb $< || true

all: main.mmb rc4transform.mmb

main.mmb: main.mmo
main.mmo: main.mms
main.mms: main.mmS        \
          MMIX.mmS        \
          abort.mmS       \
          bzero.mmS       \
          errno.mmS       \
          isalnum.mmS     \
          isalpha.mmS     \
          isascii.mmS     \
          iscntrl.mmS     \
          isdigit.mmS     \
          isgraph.mmS     \
          islower.mmS     \
          isspace.mmS     \
          isupper.mmS     \
          malloc.mmS      \
          memset.mmS      \
          perror.mmS      \
          printX.mmS      \
          rc4.mmS         \
          rotate.mmS         \
          strchr.mmS      \
          strcpy.mmS      \
          strlen.mmS      \
          strncpy.mmS     \
          strrchr.mmS     \
          strstr.mmS      \
          sys_errlist.mmS \
          tolower.mmS     \
          toupper.mmS

rc4transform.mmb: rc4transform.mmo
rc4transform.mmo: rc4transform.mms
rc4transform.mms: rc4transform.mmS MMIX.mmS strlen.mmS rc4.mmS

clean:
	$(RM) -f *.mmb *.mml *.mmo *.mms

# Slutt på GNUmakefile.