[comp.sys.mac.programmer] Can anyone anser these Questions?

rcbaem@eutrc3.urc.tue.nl (Ernst Mulder) (08/23/89)

 Well, anyway. Thank you for trying to answer my previous questions. At this
time all problems are solved. I even started a new project. I finished this
program, and well, getting the hang of it, I thought why not start a new
one? But I'm faced with a new problem:

 I have a very nice calculator, called a PC-2 (Radio Shack) known as a
PC-1500 (Sharp) as well (it's originally a Sharp machine). Since the only
calculator resembling an existing one, on the Mac, I know of is a DA
version of HP's HP12, I desided to write my own one.
 The program is finished (took one evening :) except for one (essential) thing:
I have to write an interpreter for the PC-2's machine code. The PC-2 is
both BASIC and Machine-code programmable, so I'll HAVE to write an
interpreter implementing the PC-2's microprocessor.

The problems:

1: The interpreter is probably going to be very slow.
2: The PC-2 can access 64K bytes of memory. Therefore I allocated a 64K
   locked object, with a pointer to it. Let's call this pointer memStart.

   Then I got a terrible fight with Pascal...

   The PC-2's processor has 16bit registers. So I have to access bytes
   in the 64K memory block. An instruction like LDA (P) could
   be implemented as follows (in pascal): (A is a Byte, P is an integer
   resembling a register of the PC-2's processor)

         A := Ptr(LongInt(memStart) + P)^;

   PROBLEM!! Assume P has the (integer) value -1. (=$FFFF) and say
   memStart = 0; (LongInt(memStart) + P) then gives -1 instead of $FFFF..
   Whatever typecasting I tried, I end up with $FFFF beging extended
   to the LongInt $FFFFFFFF... I finally found a solution as follows:

   type register = record case boolean of
                     true: (h:integer;
                            l:integer);
                     false:(hl:LongInt)
                   end; 

   var P:register;

   When at initialisation time P.hl is set to 0 the following DOES work
   as expected:
        P.hl := 0;

        p.l := 0;
        p.l := p.l - 1;    (p.l is now $FFFF (or -1))

        A := Ptr(LongInt(memStart) + p.hl)^;

   (When memStart had the value 0, then this addition would indeed give
    the wanted address $FFFF).

Some suggestions of mine are:

1: a) Don't try to write this program, it's bound to be slow.
   b) Write it in assembly instead of in Pascal. (But LSP's code is
      rather efficient, I found extremely nice trics wandering through
      disassembled LSP compiled programs..)
   c) Claim the program runs on 68030 Macs only :)

2: Pascal is a terribly rotten language thanks to it's excellent type
   restrictions. Write it in Assembly or in C..

Okay, but I don't have an Assembler, nor a C compiler..

Any ideas?

 Ernst.
   >

sdh@wind.bellcore.com (Stephen D Hawley) (08/23/89)

In article <864@eutrc3.urc.tue.nl> rcbaem@eutrc3.uucp writes:
>         A := Ptr(LongInt(memStart) + P)^;
>
>   PROBLEM!! Assume P has the (integer) value -1. (=$FFFF) and say
>   memStart = 0; (LongInt(memStart) + P) then gives -1 instead of $FFFF..
>   Whatever typecasting I tried, I end up with $FFFF beging extended
>   to the LongInt $FFFFFFFF... I finally found a solution as follows:

Your problem is that things are being sign extended, and you don't want them
to be.  I forget the exact Pascal standard [sic], but I believe you can
declare variables to be unsigned.  I think you might also want to try the
following as well:

const MEMSIZE = 65535;

type memtype = array[0..MEMSIZE] of char;

var mem: Ptr;

Procedure InitMem;
{ allocate memory }
begin
	mem := NewPtr(MEMSIZE);
end;

Function ReadMem(MAR:integer): char;
{ If Pascal has an unsigned integer, use that instead of a plain old
  integer.  It will run faster.  Also, mym memory is rusty as to the
  way that Pascal does type casting, but basically, I'm trying to treat
  the Pointer as an array address and address the bytes appropriately.
  The longint cast will sign extend, and the MOD should strip the
  upper word away.
}
begin
	ReadMem = memtype(mem)[longint(MAR) MOD MEMSIZE];
end;

Procedure WriteMem(MAR: integer; MDR: char);
{ similar }
begin
	memtype(mem)[longing(MAR) MOD MEMSIZE] := MDR;
end;

Oh, BTW,  MAR and MDR are the memory address register and memory data register.

Good luck.

Steve Hawley
sdh@flash.bellcore.com
"Up is where you hang your hat."
	--Jim Blandy, computer scientist

grue@lance.hss.bu.oz (Frobozz) (08/25/89)

In article <864@eutrc3.urc.tue.nl> rcbaem@eutrc3.uucp writes:
> I have a very nice calculator, called a PC-2 (Radio Shack) known as a
>PC-1500 (Sharp) as well (it's originally a Sharp machine). Since the only
so do I its a HP-28 :-)

>calculator resembling an existing one, on the Mac, I know of is a DA
>version of HP's HP12, I desided to write my own one.
> The program is finished (took one evening :) except for one (essential) thing:
>I have to write an interpreter for the PC-2's machine code. The PC-2 is
>both BASIC and Machine-code programmable, so I'll HAVE to write an
>interpreter implementing the PC-2's microprocessor.
>
>The problems:
>
>1: The interpreter is probably going to be very slow.
It may actually be faster than the original calculator (the PC-1500 wasn't
exactly the fastest machine in the world).

>2: The PC-2 can access 64K bytes of memory. Therefore I allocated a 64K
>   locked object, with a pointer to it. Let's call this pointer memStart.
>
>   Then I got a terrible fight with Pascal...
>
>   The PC-2's processor has 16bit registers. So I have to access bytes
>   in the 64K memory block. An instruction like LDA (P) could
>   be implemented as follows (in pascal): (A is a Byte, P is an integer
>   resembling a register of the PC-2's processor)
>
>         A := Ptr(LongInt(memStart) + P)^;
>
>   PROBLEM!! Assume P has the (integer) value -1. (=$FFFF) and say
>   memStart = 0; (LongInt(memStart) + P) then gives -1 instead of $FFFF..
>   Whatever typecasting I tried, I end up with $FFFF beging extended
>   to the LongInt $FFFFFFFF... I finally found a solution as follows:
>
>   type register = record case boolean of
>                     true: (h:integer;
>                            l:integer);
>                     false:(hl:LongInt)
>                   end; 
>
>   var P:register;
>
>   When at initialisation time P.hl is set to 0 the following DOES work
>   as expected:
>        P.hl := 0;
>
>        p.l := 0;
>        p.l := p.l - 1;    (p.l is now $FFFF (or -1))
>
>        A := Ptr(LongInt(memStart) + p.hl)^;
>
>   (When memStart had the value 0, then this addition would indeed give
>    the wanted address $FFFF).
You have managed to simulate unsigned long integers :-)

>
>Some suggestions of mine are:
>
>1: a) Don't try to write this program, it's bound to be slow.
It can be made reasonable, there exist emulators for 8088/6502/z80 already
for the mac and although they are slow they are not impossibly slow.
( I started on a 0.8MHz 8080A machine :-)

>   b) Write it in assembly instead of in Pascal. (But LSP's code is
>      rather efficient, I found extremely nice trics wandering through
>      disassembled LSP compiled programs..)
Assembly would be faster and for a production program trying to get maximal
speed it might be advisable, but for personal usage only it would not be
necessary.

>   c) Claim the program runs on 68030 Macs only :)
nice idea!

>
>2: Pascal is a terribly rotten language thanks to it's excellent type
>   restrictions. Write it in Assembly or in C..
The problem mentioned above doesn't occur in C [ just make everything unsigned ]
and in assembler anything goes. But, the lack of type-checking and array-bounds
checking has caused me major problems [ that why I'm currently using Simula ]
but often it does save pulling some interesting tricks.

>
>Okay, but I don't have an Assembler, nor a C compiler..
>
>Any ideas?
enter hex via a debugger (real programmers use octal, but hex is so much
cleaner).



my real suggestions:

1) Define a function that does the required conversion ( runs very slow )

2) try and trick the compilier into generating inline code for the operation
	declare the following:

		FUNCTION Convert(x: Integer): LongInt;
		INLINE $7000,$301F,$2E80;

	which defines the following assembly:

		moveq  #0, d0
		move.w (sp)+, d0
		move.l d0, (sp)

	which I hope will perform the necessary conversion without the overhead
	of making a function call. It is not as efficient as doing it in
	assembly code directly since the argument is push onto the stack and the
	result has to be poped off again, but the overhead is a lot less than
	a function call.

	I am not sure that the above assembly is correct since I haven't
	actually run the code, but I think it is ok. Also the inlined op-codes
	could be incorrect since I hand assembled the stuff (actually I first
	produced the hex & then had to dis-assemble it by hand :-) Also, my
	pascal could be wrong [ I personally HATE the language ].

	The technique using the variant record is probably more efficient than
	what I suggest above ( especially if the record is declared globally
	and the hi-word is set to zero during program initialization.

3) Use the PC-1500 ;-}





I hope this has been of some use to you.


						Pauli
seeya
SNIF
--