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 --