It's unlikely that most Gigatron owners get involved with the native 8-bit assembly language - because it is very much wrapped up in the ROM.
However, I have been working on a hardware simulation, using H. Neemann's "Digital" simulator, and I am now working at the native assembly level.
I have created a table of instructions and opcodes for the TASM assembler, and by using some macros, I can make the programming model of the Gigatron look a little more like a Z80, which is my most familiar cpu, from an assembly language point of view.
The Gigatron lacks an ADC (Add with Carry) instruction, and this is something I am currently trying to implement as a macro.
Would anyone with intimate knowledge of the native instruction set possibly explain how I can detect a carry and branch accordingly. Effectively making a macro for Branch on Carry Set.
Thanks in advance
Gigatron Assembly Language
Forum rules
Be nice. No drama.
Be nice. No drama.
Re: Gigatron Assembly Language
Here's a truth table and K-Map I created for this exact problem:
If you just want native code, then you'll need to do something like this:
This assumes the code is in page3 and there is no extra level of indirection.
The way it works is to add the low bytes of a two 16bit, (word), variables together and then check the sign bit of the 8bit result, if the sign is negative then AND the sign bits of the two input low bytes together, otherwise OR the sign bits of the two input low bytes together; this is your carry bit.
If you look at the final equation, you can see that's exactly what this code does.
For your particular use-case you would probably do something like this:
Code: Select all
// Calculate carry using signed 8bit representation for : r = a + b
//
// Sr = sgn(r), Sa = sgn(a), Sb = sgn(b), C = carry
//
// Sr | Sa | Sb || C
// ----+----+----++---
// 0 | 0 | 0 || 0
// 0 | 0 | 1 || 1
// 0 | 1 | 0 || 1
// 0 | 1 | 1 || 1
// 1 | 0 | 0 || 0
// 1 | 0 | 1 || 0
// 1 | 1 | 0 || 0
// 1 | 1 | 1 || 1
//
// __ __ __ __
// Sa.Sb Sa.Sb Sa.Sb Sa.Sb
// __ +-----+-----+-----+-----+
// Sr | 0 | 1 | 1 | 1 |
// +-----+-----+-----+-----+
// Sr | 0 | 0 | 1 | 0 |
// +-----+-----+-----+-----+
//
// __ __
// C = Sa.Sb + Sr.Sb + Sr.Sa
// __
// C = Sa.Sb + Sr.(Sb + Sa)
Code: Select all
ld(AC,X) #10 Address of low byte to be added
adda(1) #11
st([vTmp]) #12 Address of high byte to be added
ld([vAC]) #13 Add the low bytes
adda([X]) #14
st([vAC]) #15 Store low result
bmi('.addw#18') #16 Now figure out if there was a carry
suba([X]) #17 Gets back the initial value of vAC
bra('.addw#20') #18
ora([X]) #19 Carry in bit 7
label('.addw#18')
anda([X]) #18 Carry in bit 7
nop() #19
label('.addw#20')
anda(0x80,X) #20 Move carry to bit 0
ld([X]) #21
adda([vAC+1]) #22 Add the high bytes with carry
ld([vTmp],X) #23
adda([X]) #24
st([vAC+1]) #25 Store high result
bra('NEXT') #26
ld(-28/2) #27
The way it works is to add the low bytes of a two 16bit, (word), variables together and then check the sign bit of the 8bit result, if the sign is negative then AND the sign bits of the two input low bytes together, otherwise OR the sign bits of the two input low bytes together; this is your carry bit.
If you look at the final equation, you can see that's exactly what this code does.
For your particular use-case you would probably do something like this:
Code: Select all
ld(AC,X) #10 Address of low byte to be added
adda(1) #11
st([vTmp]) #12 Address of high byte to be added
ld([vAC]) #13 Add the low bytes
adda([X]) #14
st([vAC]) #15 Store low result
bmi('.addw#18') #16 Now figure out if there was a carry
suba([X]) #17 Gets back the initial value of vAC
bra('.addw#20') #18
ora([X]) #19 Carry in bit 7
label('.addw#18')
anda([X]) #18 Carry in bit 7
nop() #19
label('.addw#20')
anda(0x80,X) #20 Move carry to bit 0
ld([X]) #21
bne('wherever') #22 Branch on carry
Re: Gigatron Assembly Language
Thankyou for your excellent explanation.
I could not understand exactly what the AND / OR instructions were doing.
I was trying to work out how the carry was detected from Cout, not realising that it could be determined from the sign bit of the two operands.
This makes it clear now.
Thanks
I could not understand exactly what the AND / OR instructions were doing.
I was trying to work out how the carry was detected from Cout, not realising that it could be determined from the sign bit of the two operands.
This makes it clear now.
Thanks