OT: Altair32: C arrays and pointers

From: Sean 'Captain Napalm' Conner <spc_at_conman.org>
Date: Sat May 19 22:34:10 2001

It was thus said that the Great Richard A. Cini, Jr. once stated:
>
> Hello, all:
>
> Futher errors have been found in the Altair32 8080 processor emulator code
> by some eagle-eyed users. So, I'm trying to fix them, but my lack of depth
> in C programming has become evident. So, I'd like to enlist some help again.
>
> Here's the code (cut and paste; written by Claus Giloi):

  Okay, as one of the few token C programmers here, I'll take a shot at
this. I'll give several solutions of varying amount of portability and
speed, so pick wisely 8-) The code is ANSI C, which was passed in 1989,
making it on topic for this group 8-P

> uchar regs[8] ; // A, F, B, C, D, E, H, L - actual storage order!
> // 0 1 2 3 4 5 6 7
>
> // pointer array for sss, ddd addressing
> uchar * b_regs[8]=
> {&regs[2],&regs[3],&regs[4],&regs[5],&regs[6],&regs[7],&dummy,&regs[0]} ;
> // B C D E H L trap! ACC
>
> // pointer array for rp addressing
> ushort * w_regs[4] =
> { (ushort *)&regs[2], (ushort *)&regs[4], (ushort *)&regs[6], &SP } ;
> // B D H SP
>

  The following assumes an 8-bit character, 2 character in a short (most
modern machines), either big endian or little endian (you need to define
LITTLE_END):

#include <limits.h>

        /*---------------------------------------------
        ; if Intel based, set to 1, otherwise (say, for
        ; Motorola systems) set to 0
        ;---------------------------------------------*/

#define LITTLE_END 1

#if CHAR_BIT != 8
# error No 8bit bytes supported on this system
#else
   typedef unsigned char byte;
#endif

#if (USHRT_MAX != 65535UL)
# error No 16bit type supported on this system
#else
   typedef unsigned short word;
#endif

union defregs
{
  byte b[2];
  word w;
} regs[4]; /* AF , BC, DE, HL */

#if LITTLE_END
# define A regs[0].1[1]
# define F regs[0].l[0]
# define B regs[1].l[1]
# define C regs[1].l[0]
# define D regs[2].l[1]
# define E regs[2].l[0]
# define H regs[3].l[1]
# define L regs[3].l[0]
#else
# define A regs[0].l[0]
# define F regs[0].l[1]
# define B regs[1].l[0]
# define C regs[1].l[1]
# define D regs[2].l[0]
# define E regs[2].l[1]
# define H regs[3].l[0]
# define L regs[3].l[1]
#endif

#define BC regs[1].w
#define DE regs[2].w
#define HL regs[3].w

  You now have an easier way to reference the registers, the following
code:

> switch ((u&RP_MASK)>>4){ // RP_MASK isolates register pairs
> case 2: //HL
> tmpH = *pH ; // pointer to H storage
> tmpL = tmpL2 = *pL ;
> tmpL++;
> if (((tmpL & 0xff) == 0) && (tmpL2 == 0xff)) tmpH++ ;
> *pH = tmpH ; // save regs
> *pL = tmpL ;
> break ;
> // other cases omitted.
> }

  Can be replaced with:

                switch((u & RP_MASK) >> 4)
                {
                  case 2: /* HL */
                        HL++;
                        break;
                  /* other cases */
                }

  To increment a register pair and check for carry (say, BC):

                unsigned long tmp;

                tmp = BC;
                tmp++;
                if (tmp > USHRT_MAX)
                {
                  /* set carry flag */
                }
                BC = tmp & 0xFFFFul;

  The more portable, but slower method (and not dependant upon endianness)
is:

#include <limits.h>

typedef unsigned char byte;

byte regs[8];

#define A regs[0]
#define F regs[1]
#define B regs[2]
#define C regs[3]
#define D regs[4]
#define E regs[5]
#define H regs[6]
#define L regs[7]

#define rBC ( ((B) << 8) | (C) )
#define rDE ( ((D) << 8) | (E) )
#define rHL ( ((H) << 8) | (L) )

        /*------------------------------------------------------------
        ; The following macros evaluate the parameter more than once.
        ; be careful on how you use these. Beware of side effects!
        ;------------------------------------------------------------*/

#define wBC(w) (B) = ((w) >> 8) & 0xFF) ; (C) = ((w) & 0xFF)
#define wDE(w) (D) = ((w) >> 8) & 0xFF) ; (E) = ((w) & 0xFF)
#define wHL(w) (H) = ((w) >> 8) & 0xFF) ; (L) = ((w) & 0xFF)


                switch((u & RP_MASK) >> 4)
                {
                  unsigned int tmp;

                  case 2: /* HL */
                       tmp = rHL + 1;
                       wHL(tmp);
                       break;
                  /* other cases */
                }

                /*-------------------------------------
                ; That carry thang ...
                ;--------------------------------------*/

                unsigned long tmp;

                tmp = BC;
                tmp++;
                if (tmp > USHRT_MAX)
                {
                  /* set carry flag */
                }
                wBC(tmp);

  Sigh. I've been programming in C for waaaaay too long 8-)

  -spc (Sorry about the C code ... )
Received on Sat May 19 2001 - 22:34:10 BST

This archive was generated by hypermail 2.3.0 : Fri Oct 10 2014 - 23:34:09 BST