[Coco] 6309 MULD real and emulators

Walter Zambotti zambotti at iinet.net.au
Mon Oct 28 02:41:33 EDT 2019


And I managed to get muld to perform the 32 variable (0-31+) bit shift.

The function takes about 197 cycles regardless of number of bits.  Except for the special case of 16 bits where it takes 99 cycles.

It confirms to OS9 C ABI stack and result passing convention.

/*#include <stdio.h>*/

unsigned long shfl32(val, shft)
unsigned long val;
short shft;
{
  return val<<shft;
}

unsigned long shfl32a(val, shft)
unsigned long val;
short shft;
{
#asm 
* 10,s pointer to long result
* 4,s 4 byte value
* 8,s 2 byte shift
* d = shift amount
* x = pointer to result
  ldx 10,s
  ldd 8,s
* if shift amount is greater than 31 then
* just return zero
  cmpd #32
  blt _10x
  ldq #0
  stq 4,s
  bra _13x
* if shift amount is greater than 16 than
* move bottom word of value into top word 
* and clear bottom word  
_10x
  cmpb #16
  blt _1x
  ldu 6,s
  stu 4,s
  clr 6,s
  clr 7,s
_1x
* setup pointer u and offset e into mult table _2x
  leau _2x,pc
  andb #15
* if there is no shift value just return value
  beq _13x
  aslb * need to double shift to use as word table offset
  stb 8,s     * save double shft
  tfr b,e 
* shift top word q = val.word.high * multtab[shft]
  ldd 4,s
  muld e,u
  stw ,x * result.word.high = low word of mult
* shift bottom word q = val.word.low * multtab[shft]
  lde 8,s     * reload double shft
  ldd 6,s
  muld e,u
  stw 2,x     * result.word.low = low word of mult
* The high word or mult needs to be corrected for sign
* if val is negative then muld will return negated results
* and need to un negate it
  lde 8,s     * reload double shift
  tst 4,s     * test top byte of val for negative
  bge _11x
  addd e,u    * add the multtab[shft] again to top word 
_11x
* if multtab[shft] is negative (shft is 15 or shft<<1 is 30)
* also need to un negate result
  cmpe #30
  bne _12x
  addd 6,s    * add val.word.low to top word
_12x
* combine top and bottom and save bottom half of result 
  ord ,x
  std ,x
  bra _14x
* this is only reached if the result is in value (let result = value) 
_13x
  ldq 4,s     * load value
  stq ,x      * result = value
_14x
  puls u,pc
_2x fdb $01,$02,$04,$08,$10,$20,$40,$80,$0100,$0200,$0400,$0800
   fdb $1000,$2000,$4000,$8000
#endasm
}

unsigned long val, val1, val2;
short shft;

int main(argc, argv)
int argc;
char *argv[];
{
  /*long val, val1, val2;
  short shft;*/
  unsigned long dummy = 0;
  /*long (*shftstfunc)(long, short);*/

  pflinit();
  
  sscanf(argv[1], "%D", &val);
  shft = (short)atoi(argv[2]);
  /* val = 1; shft = 1;*/
  printf("%lx %d\n", val, shft);
  val1 = shfl32(val, shft);
  val2 = shfl32a(val, shft);
  printf("%lx\n", val1);
  printf("%lx\n", val2);
  return 0;
  /*
  shft = (short)atoi(argv[1]);

  if(shft == 1)
  {
     printf("shfl32\n");
     shftstfunc = shfl32;
  }
  else
  {
     printf("shfl32a\n");
     shftstfunc = shfl32a;
  }
  */

  for(val = 1 ; val < 1000000 ; val++)
  {
    for(shft = 0 ; shft < 32 ; shft++)
    {
      /*printf("%lx ", shfl32(val, shft));*/
      /*printf("%lx\n", shfl32a(val, shft));*/
      val1 = 0 + shfl32(val, shft);
      val2 = 0 + shfl32a(val, shft);
      /*printf("%lx ", val1);*/
      /*printf("%lx\n", val2);*/
      if (val1 != val2)
      {
        printf("%lx %d = %lx %lx\n", val, shft, val1, val2);
      }
    }
  }
}


-----Original Message-----
From: Coco [mailto:coco-bounces at maltedmedia.com] On Behalf Of Walter Zambotti
Sent: Friday, 25 October 2019 2:04 PM
To: 'CoCoList for Color Computer Enthusiasts' <coco at maltedmedia.com>
Subject: Re: [Coco] 6309 MULD real and emulators

Robert

On OVCC it has already been correct in version 1.1.

In my recent 6309 emulator rewrite in X86 assembly I added all the missing ops and corrected some other 6309 ops that I thought were not correct.

I also did this in the C version.  The C version should be backwards portable to VCC with very little effort.

Walter	

Here is the OVCC muld C code

void Muld_M(void)
{ //118F Phase 5 6309
	Q_REG =  (signed short)D_REG * (signed short)IMMADDRESS(PC_REG);
	cc[C] = 0; 
	cc[Z] = ZTEST(Q_REG);
	cc[V] = 0;
	cc[N] = NTEST32(Q_REG);
	PC_REG+=2;
	CycleCounter+=28;
}

-----Original Message-----
From: Coco [mailto:coco-bounces at maltedmedia.com] On Behalf Of Robert Gault
Sent: Friday, 25 October 2019 10:47 AM
To: CoCoList for Color Computer Enthusiasts <coco at maltedmedia.com>
Subject: [Coco] 6309 MULD real and emulators

There was a question posted about the 6309 opcode MULD. That is a multiplication of the content of regD with Immediate, Direct, Extended, or Indexed numbers. What makes it different from the opcode MUL is that MULD is a signed multiplication.

However, be warned that while for a real 6309, and the MAME/MESS emulator MULD is signed, it is unsigned with VCC v2.0.1. VCC should be corrected!
ex.
  real 6309
  ldd #$8001
  muld #$8001
  regQ = $3FFF0001

  VCC
  ldd #$8001
  muld #$8001
  regQ = $40010001     Correct if the multiplication was unsigned.

You can get the same $3FFF0001 answer with real 6309
  ldd #$7FFF
  muld #$7FFF
regQ = $3FFF0001

Now since $10000-$7FFF=$8001 the above signed math makes sense as $8001=-$7FFF.

Robert

--
Coco mailing list
Coco at maltedmedia.com
https://pairlist5.pair.net/mailman/listinfo/coco


-- 
Coco mailing list
Coco at maltedmedia.com
https://pairlist5.pair.net/mailman/listinfo/coco



More information about the Coco mailing list