02-24-2016, 12:31 PM
Post: #1
 smp Senior Member Posts: 463 Joined: Jul 2015
Hello again,

I have been working on my 8080 emulator project, and I've so far been simply using variables to hold the data fetched out of a single column matrix as an instruction, or the contents of an emulated 8080 data register.

This has been fine for coding up the MOV, LDA, STA, INR, DCR type of instructions, but the arithmetic instructions need to do the arithmetic properly.

I am confused about variables in PPL. Is there a way to specifically declare a variable to be an integer? I see the integer arithmetic commands, but I have not been able to find how to constrain a variable to be an 8 bit or 16 bit integer.

smp
02-24-2016, 03:05 PM
Post: #2
 Tim Wessman Senior Member Posts: 2,293 Joined: Dec 2013
There is no way to constrain anything such as traditional "typed" variables. However, you can set the size on a fixed size home integer. For example, #FF:16h In this case, you can probably be certain that you've stored an integer with the correct word size by doing :16h, :-8h (signed 8), etc

TW

Although I work for HP, the views and opinions I post here are my own.
02-25-2016, 12:55 AM
Post: #3
 smp Senior Member Posts: 463 Joined: Jul 2015
(02-24-2016 03:05 PM)Tim Wessman Wrote:  However, you can set the size on a fixed size home integer. For example, #FF:16h In this case, you can probably be certain that you've stored an integer with the correct word size by doing :16h, :-8h (signed 8), etc

Thank you very much, Tim for the guidance.

Let's see if I understand you correctly. When I fetch an instruction from the vector, I would do it like this:

D1:=M1(P1):16h;

And that will store it as a 16 bit integer, right?

I also need to perform operations like this:

A:=M1((H*256)+L);

So I need to code that as:

A:=M1((H*256)+L):16h;

Is that right, or would I need to add the :16h suffix onto all of the elements?

Thanks,
smp
02-25-2016, 06:22 AM
Post: #4
 cyrille de brébisson Senior Member Posts: 1,047 Joined: Dec 2013
Hello,

Nope, you have it wrong...

#.....:-nb
where ... is a number, n is a number of bits and b is b, o, d or h is the syntax for entering integers... But it does not Convert anything to integers.
R->B is the operation that converts a real to a binary.
you can also look at SetBits and SetBase that allow to modify the binary number.

As Tim was saying there is no variable typing in HPPL (with the obvious exception of the build in A-Z, Z?, L? and M? variables).

How are you proposing to store your data?
Program instructions
Cpu registers
I would advise that you use lists (easiest), or you could use a string for the program and named variables for the CPU registers.

One thing with int containing variables, you can access bits directly by doing var(bit) or a sub part of the integer by doing var(start_bit, nb_bits)... This works in read and write and can be very useful.
for example, if you have a AX variable (register A), you can access AL by doing AX(0,8) and AH by doing AX(8,8)

Cyrille

Although I work for the HP calculator group, the views and opinions I post here are my own. I do not speak for HP.
02-26-2016, 09:58 PM (This post was last modified: 02-27-2016 10:13 PM by smp.)
Post: #5
 smp Senior Member Posts: 463 Joined: Jul 2015

I have started to get some of my arithmetic code to work properly by using the R->B() command and using the #xx:16h notation on numbers when I perform initialization.

Currently, I am using LOCAL variables for my 8080 registers and flags. I am initializing my them like this:
Code:
 // // initialization // // initialize 8080 registers & flags   pc:=#1:17h;     // program counter  // vector M1 starts with location 1, not 0   sp:=#0:17h;     // stack pointer   a:=#0:8h;      // accumulator   b:=#0:8h;      // B register   c:=#0:8h;      // C register   d:=#0:8h;      // D register   ee:=#0:8h;     // E register   h:=#0:8h;      // H register   l:=#0:8h;      // L register   cf:=0;     // carry flag   z:=0;      // zero flag   ac:=0;     // auxiliary carry flag   s:=0;      // sign flag   p:=0;      // parity flag // initialize temporary variables   d1:=#0:8h;     // instruction fetched from RAM   d2:=#0:8h;     // second byte of a multi-byte instruction   d3:=#0:8h;     // third byte of a multi-byte instruction   t1:=#0:17h;    // temp (larger than 16 bits to capture carry) // initialize run flags   r1:=1;     // run flag 1   r2:=1;     // run flag 2 // clear the terminal screen   PRINT; //

I am setting up M1 as a one-column array (or vector) for simulating the memory so I can retrieve instructions like this:
Code:
 d1:=M1(pc);

I am incrementing the program counter like this:
Code:
     pc:=pc+#1:17h;     IF pc>#0FFFF:17h THEN       pc:=#1:17h;  // vector M1 starts with location 1, not 0     END;

The bit of code that I've been playing with this afternoon is this:
Code:
   IF d1==57 THEN // DAD SP (HL+SP)     t1:=#0:17h;     t1:=t1+h;     t1:=t1*#100:9h+l+sp;     h:=(t1/#100:9h) AND #FF:8h;     l:=(t1 AND #FF:8h);     CARRY16;   END; CARRY16() BEGIN   cf:=0;   IF (t1>#0FFFF:17h) THEN     cf:=1;   END; END;

I have my t1 (temporary) register initialized larger than 16 bits so I can capture the carry from 16 bit arithmetic. The combining of the H and L registers into one 16 bit register, the 16 bit addition with the SP register, and the masking of the H and L registers after the addition are all working properly, BUT h and l both become 17 bit variables.

The 16 bit addition with the result going into the 17 bit t1 variable shows a 17 bit result in the case of a carry overflow, so then I can test t1 for being greater than FFFF as you see. This is working as it should.

I'm happy to be making progress, but I am still learning...

Thanks very much for all your attention and assistance.

smp
02-29-2016, 06:14 AM
Post: #6
 cyrille de brébisson Senior Member Posts: 1,047 Joined: Dec 2013
Hello,

You should be able to speed your carry by doing a shift operation, or a bit grab operation on the register. Something like cf:= t1(16); for example. Much faster than the CARY16 function call and it's implementation.

You might be able to handle memory in a string (limited to 64K), it would be more memory efficient (2 bytes per memory byte), and probably faster.

Cyrille

Although I work for the HP calculator group, the views and opinions I post here are my own. I do not speak for HP.
02-29-2016, 05:25 PM
Post: #7
 smp Senior Member Posts: 463 Joined: Jul 2015
(02-29-2016 06:14 AM)cyrille de brébisson Wrote:  Hello,

You should be able to speed your carry by doing a shift operation, or a bit grab operation on the register. Something like cf:= t1(16); for example. Much faster than the CARY16 function call and it's implementation.

You might be able to handle memory in a string (limited to 64K), it would be more memory efficient (2 bytes per memory byte), and probably faster.

Cyrille

Hi Cyrille,

Thanks very much, once again, for your advice and ideas. I will look to changing my carry operations to be as you suggest. I agree that what you suggest will be much faster than branching to a subroutine to perform the operations.