home *** CD-ROM | disk | FTP | other *** search
/ Virtual Reality Homebrewer's Handbook / vr.iso / vr386 / miscmath.asm < prev    next >
Assembly Source File  |  1996-03-19  |  10KB  |  571 lines

  1.     TITLE    MISCMATH - VARIOUS MATH IN ASSEMBLER
  2.  
  3.     COMMENT $
  4.  
  5. // Routines to do various math that can't be done in C.
  6. // Some are just for efficiency, and could be done in C with
  7. // a true 32-bit compiler.  Others use 64-bit intermediate results.
  8.  
  9. // All code by Dave Stampe, last updated 23/12/93
  10.  
  11. /*
  12.  This code is part of the VR-386 project, created by Dave Stampe.
  13.  VR-386 is a desendent of REND386, created by Dave Stampe and
  14.  Bernie Roehl.  Almost all the code has been rewritten by Dave
  15.  Stampre for VR-386.
  16.  
  17.  Copyright (c) 1994 by Dave Stampe:
  18.  May be freely used to write software for release into the public domain
  19.  or for educational use; all commercial endeavours MUST contact Dave Stampe
  20.  (dstampe@psych.toronto.edu) for permission to incorporate any part of
  21.  this software or source code into their products!  Usually there is no
  22.  charge for under 50-100 items for low-cost or shareware products, and terms
  23.  are reasonable.  Any royalties are used for development, so equipment is
  24.  often acceptable payment.
  25.  
  26.  ATTRIBUTION:  If you use any part of this source code or the libraries
  27.  in your projects, you must give attribution to VR-386 and Dave Stampe,
  28.  and any other authors in your documentation, source code, and at startup
  29.  of your program.  Let's keep the freeware ball rolling!
  30.  
  31.  DEVELOPMENT: VR-386 is a effort to develop the process started by
  32.  REND386, improving programmer access by rewriting the code and supplying
  33.  a standard API.  If you write improvements, add new functions rather
  34.  than rewriting current functions.  This will make it possible to
  35.  include you improved code in the next API release.  YOU can help advance
  36.  VR-386.  Comments on the API are welcome.
  37.  
  38.  CONTACT: dstampe@psych.toronto.edu
  39. */
  40.         $
  41.  
  42.     .MODEL large
  43.  
  44. ; # define XFSC 536870912   /* 2**29 for shifting xform coeffs to long */
  45.  
  46.  
  47.     .DATA
  48.  
  49. _longmath_overflow    dd 0    ;; overflow/high dword return
  50.  
  51.     .CODE INTMATH
  52.  
  53.  
  54. MULT29     MACRO a,b                 ; multiply <3.29> -> eax
  55.     mov    eax,DWORD PTR a
  56.     imul    DWORD PTR b
  57.     shrd    eax,edx,29
  58.     adc    eax,0
  59.     ENDM
  60.  
  61. MMULT29 MACRO a,b,c               ; multiply 3 of <3.29> -> eax
  62.     mov    eax,DWORD PTR a
  63.     imul    DWORD PTR b
  64.     shrd    eax,edx,29
  65.     adc    eax,0
  66.     imul    DWORD PTR c
  67.     shrd    eax,edx,29
  68.     adc    eax,0
  69.     ENDM
  70.  
  71. DOTPROD    MACRO a,b,c,x,y,z,p      ; dot product plus p, accum in ecx:ebx
  72.     mov    eax,a            ; result in eax
  73.     imul    DWORD PTR x
  74.     mov    ecx,edx
  75.     mov    ebx,eax
  76.     mov    eax,b
  77.     imul    DWORD PTR y
  78.     add    ebx,eax
  79.     adc    ecx,edx
  80.     mov    eax,c
  81.     imul    DWORD PTR z
  82.     add    eax,ebx
  83.     adc    edx,ecx
  84.     shrd    eax,edx,29
  85.     adc    eax,p
  86.     ENDM
  87.  
  88. ;/****************** MISC. MATH SUPPORT **********/
  89.  
  90.  
  91.  
  92. ;long m_mult(long a, long b)    /* perform mult. by matrix element         */
  93. ;{                              /* where either a or b is in <3.29> format */
  94.  
  95. a    equ    [bp+8]          ; arguments
  96. b    equ    [bp+12]
  97.  
  98.     PUBLIC    _m_mult
  99.  
  100. _m_mult    proc    far
  101.  
  102.     .386
  103.     push    ebp
  104.     mov    ebp,esp
  105.  
  106.     MULT29    a,b
  107.  
  108.     shld    edx,eax,16    ; return in dx:ax
  109.  
  110.     mov    esp,ebp
  111.     pop    ebp
  112.     ret
  113.  
  114. _m_mult    endp
  115.  
  116.  
  117. ;long m2_mult(long a, long b, long c)    /* perform mult. by matrix element         */
  118. ;{                              /* where a and b is in <3.29> format */
  119.  
  120. a    equ    [bp+8]          ; arguments
  121. b    equ    [bp+12]
  122. b    equ    [bp+16]
  123.  
  124.     PUBLIC    _m_mult
  125.  
  126. _m2_mult    proc    far
  127.  
  128.     .386
  129.     push    ebp
  130.     mov    ebp,esp
  131.  
  132.     MMULT29    a,b,c
  133.  
  134.     shld    edx,eax,16    ; return in dx:ax
  135.  
  136.     mov    esp,ebp
  137.     pop    ebp
  138.     ret
  139.  
  140. _m2_mult    endp
  141.  
  142.  
  143.  
  144.  
  145. ;long divide_29(long a, long b) /* perform divide, result in <3.29> format */
  146. ;{                              /* up to user to test for  overflow          */
  147.  
  148. a    equ    DWORD PTR [bp+8]          ; arguments
  149. b    equ    DWORD PTR [bp+12]
  150.  
  151.     PUBLIC    _divide_29
  152.  
  153. _divide_29    proc    far
  154.  
  155.     .386
  156.     push    ebp
  157.     mov    ebp,esp
  158.  
  159.     mov    eax,a
  160.     cdq
  161.     shld    edx,eax,29
  162.     shl    eax,29
  163.  
  164.     idiv    b
  165.  
  166.     shld    edx,eax,16    ; return in dx:ax
  167.  
  168.     mov    esp,ebp
  169.     pop    ebp
  170.     ret
  171.  
  172. _divide_29    endp
  173.  
  174.  
  175. ;long divide_long(long ahi, long alo, long b)
  176.  
  177. a    equ    DWORD PTR [bp+8]          ; arguments
  178. b    equ    DWORD PTR [bp+12]
  179. b    equ    DWORD PTR [bp+16]
  180.  
  181.     PUBLIC    _divide_long
  182.  
  183. _divide_long    proc    far
  184.  
  185.     .386
  186.     push    ebp
  187.     mov    ebp,esp
  188.  
  189.     mov    eax,alo
  190.     mov    edx,ahi
  191.  
  192.     idiv    b
  193.     mov    _longmath_overflow,edx
  194.  
  195.     shld    edx,eax,16    ; return in dx:ax
  196.  
  197.     mov    esp,ebp
  198.     pop    ebp
  199.     ret
  200.  
  201. _divide_long    endp
  202.  
  203.  
  204. ;long mult_long(long a, long b) /* perform multiply on longs         */
  205.  
  206. a    equ    DWORD PTR [bp+8]          ; arguments
  207. b    equ    DWORD PTR [bp+12]
  208.  
  209.     PUBLIC    _mult_long
  210.  
  211. _mult_long    proc    far
  212.  
  213.     .386
  214.     push    ebp
  215.     mov    ebp,esp
  216.  
  217.     mov    eax,a
  218.     imul    b
  219.     mov    _longmath_overflow,edx
  220.  
  221.     shld    edx,eax,16    ; return in dx:ax
  222.  
  223.     mov    esp,ebp
  224.     pop    ebp
  225.     ret
  226.  
  227. _mult_long    endp
  228.  
  229.  
  230.  
  231. ;    // shifts 32-bit signed number left or right (>0 is left, <0 is right)
  232. ;extern long_shift32(long a, int shift);
  233.  
  234. a    equ    DWORD PTR [bp+8]          ; arguments
  235. shift    equ    WORD PTR [bp+12]
  236.  
  237.     PUBLIC    _long_shift32
  238.  
  239. _long_shift32    proc    far
  240.  
  241.     .386
  242.     push    ebp
  243.     mov    ebp,esp
  244.  
  245.     mov    eax,a
  246.     cdq
  247.     mov    cx,shift
  248.     or    cx,cx
  249.     jge    left_shift32
  250.  
  251.     neg    cx
  252.     shrd    eax,edx,cl
  253.     shr    edx,cl
  254.     adc    eax,0
  255.     adc    edx,0
  256.     mov    _longmath_overflow,edx
  257.     jmp    done_shift32
  258.  
  259. left_shift32:
  260.     shld    edx,eax,cl
  261.     shl    eax,cl
  262.     mov    _longmath_overflow,edx
  263.  
  264. done_shift32:
  265.     shld    edx,eax,16    ; return in dx:ax and eax
  266.  
  267.     mov    esp,ebp
  268.     pop    ebp
  269.     ret
  270.  
  271. _long_shift32    endp
  272.  
  273.  
  274.  
  275.  
  276. ;    // shifts 64-bit signed number left or right (>0 is left, <0 is right)
  277. ;    // msdword of result is returned in longmath_overflow
  278. ;extern long_shift64(long ahi, long alo, int shift);
  279.  
  280. ahi    equ    DWORD PTR [bp+8]          ; arguments
  281. alo    equ    DWORD PTR [bp+12]
  282. shift    equ    WORD PTR  [bp+16]
  283.  
  284.     PUBLIC    _long_shift64
  285.  
  286. _long_shift64    proc    far
  287.  
  288.     .386
  289.     push    ebp
  290.     mov    ebp,esp
  291.  
  292.     mov    edx,ahi
  293.     mov    eax,alo
  294.     mov    cx,shift
  295.     or    cx,cx
  296.     jge    left_shift64
  297.  
  298.     neg    cx
  299.     shrd    eax,edx,cl
  300.     shr    edx,cl
  301.     adc    eax,0
  302.     adc    edx,0
  303.     mov    _longmath_overflow,edx
  304.     jmp    done_shift64
  305.  
  306. left_shift64:
  307.     shld    edx,eax,cl
  308.     shl    eax,cl
  309.     mov    _longmath_overflow,edx
  310.  
  311. done_shift64:
  312.     shld    edx,eax,16    ; return in dx:ax and eax
  313.  
  314.     mov    esp,ebp
  315.     pop    ebp
  316.     ret
  317.  
  318. _long_shift64    endp
  319.  
  320.  
  321.  
  322. ;long mulmuldiv(long a, long b) /* perform (a*b)/c with 64-bit intermediate */
  323. ;{                              /* up to user to test for  overflow  */
  324.  
  325. a    equ    DWORD PTR [bp+8]          ; arguments
  326. b    equ    DWORD PTR [bp+12]
  327. c    equ    DWORD PTR [bp+16]
  328.  
  329.     PUBLIC    _mulmuldiv
  330.  
  331. _mulmuldiv    proc    far
  332.  
  333.     .386
  334.     push    ebp
  335.     mov    ebp,esp
  336.  
  337.     mov    eax,a
  338.     imul    b
  339.     idiv    c
  340.     mov    _longmath_overflow,edx
  341.  
  342.     shld    edx,eax,16    ; return in dx:ax
  343.  
  344.     mov    esp,ebp
  345.     pop    ebp
  346.     ret
  347.  
  348. _mulmuldiv    endp
  349.  
  350.  
  351.  
  352. ;long dot_prod_29(long a, long b, long c, long x, long y, long z)
  353. ; /* computes (Ax + By + Cz)>>29 */
  354.  
  355. a    equ    [bp+8]          ; arguments
  356. b    equ    [bp+12]
  357. c    equ    [bp+16]
  358. x    equ    [bp+20]
  359. y    equ    [bp+24]
  360. z    equ    [bp+28]
  361.  
  362.     PUBLIC    _dot_prod_29
  363.  
  364. _dot_prod_29    proc    far
  365.  
  366.     .386
  367.     push    ebp
  368.     mov    ebp,esp
  369.  
  370.     push    esi
  371.     push    edi
  372.     push    ecx
  373.  
  374.     DOTPROD a,b,c,x,y,z,0
  375.  
  376.     shld    edx,eax,16    ; return dx:ax
  377.  
  378.     pop    edi
  379.     pop    esi
  380.  
  381.     mov    esp,ebp
  382.     pop    ebp
  383.     ret
  384.  
  385. _dot_prod_29    endp
  386.  
  387.  
  388.  
  389. ;long scale_16(long s, long a, long x)    /* perform scaling by 16.16 number */
  390.  
  391.  
  392. s    equ    [bp+8]          ; arguments
  393. a     equ    [bp+12]
  394. x     equ    [bp+16]
  395.  
  396.     PUBLIC    _scale_16
  397.  
  398. _scale_16     proc    far
  399.  
  400.     .386
  401.     push    ebp
  402.     mov    ebp,esp
  403.  
  404.     mov    eax,DWORD PTR x
  405.     add     eax,DWORD PTR a
  406.     imul    DWORD PTR s
  407.     shrd    eax,edx,16
  408.     adc    eax,0
  409.  
  410.     shld    edx,eax,16    ; return in eax and dx:ax
  411.  
  412.     mov    esp,ebp
  413.     pop    ebp
  414.     ret
  415.  
  416. _scale_16  endp
  417.  
  418.  
  419. ;long calc_scale_16(long a, long b, long s)   /* compute 16.16 scaling factor */
  420.  
  421. a    equ    [bp+8]          ; arguments
  422. b     equ    [bp+12]
  423. s     equ    [bp+16]
  424.  
  425.     PUBLIC    _calc_scale_16
  426.  
  427. _calc_scale_16    proc    far
  428.  
  429.     .386
  430.     push    ebp
  431.     mov    ebp,esp
  432.  
  433.     xor    eax,eax        ; return 0 for divide error
  434.     mov    ebx,DWORD PTR a
  435.     sub    ebx,DWORD PTR b
  436.     je    cdiv
  437.     mov    eax, DWORD PTR s
  438.     cdq
  439.     shld    edx,eax,17
  440.     shl    eax,17
  441.     idiv  ebx
  442. cdiv:
  443.     shld    edx,eax,16    ; return in eax and dx:ax
  444.  
  445.     mov    esp,ebp
  446.     pop    ebp
  447.     ret
  448.  
  449. _calc_scale_16    endp
  450.  
  451.  
  452.  
  453.  
  454.  
  455.  
  456. ;long plane_y(long a, long b, long c, long d, long x, long z)
  457. ;         /* used to compute floor/ceiling of areas */
  458.  
  459. a    equ    [bp+8]          ; arguments
  460. b     equ    [bp+12]
  461. c     equ    [bp+16]
  462. d     equ    [bp+20]
  463. x     equ    [bp+24]
  464. z     equ    [bp+28]
  465.  
  466.     PUBLIC    _plane_y
  467.  
  468. _plane_y    proc    far
  469.  
  470.     .386
  471.     push    ebp
  472.     mov    ebp,esp
  473.             ;* computes (Ax + Cz + D)/-B */
  474.     push    esi
  475.     push    edi
  476.  
  477.     xor    eax,eax
  478.     test    DWORD PTR b,-1
  479.     je    divzero
  480.  
  481.     mov    eax,a
  482.     imul    DWORD PTR x
  483.     mov    esi,eax
  484.     mov    edi,edx
  485.  
  486.     mov    eax,c
  487.     imul    DWORD PTR z
  488.     add    esi,eax
  489.     adc    edi,edx
  490.  
  491.     mov    eax,DWORD PTR d
  492.     cdq
  493.     add    eax,esi
  494.     adc    edx,edi
  495.     idiv    DWORD PTR b
  496. divzero:
  497.     shld    edx,eax,16    ; return in eax and dx:ax
  498.     pop    edi
  499.     pop    esi
  500.  
  501.     mov    esp,ebp
  502.     pop    ebp
  503.     ret
  504.  
  505. _plane_y    endp
  506.  
  507.  
  508.  
  509.  
  510. ;/************* 32 BIT CITY-BLOCK DISTANCE *************/
  511.  
  512. ;/* returns abs(x1-x2) + abs(y1-y2) + abs(z1-z2) */
  513.  
  514. ;long big_dist(long x1, long y1, long z1,
  515. ;           long x2, long y2, long z2 )
  516.  
  517. x1    equ    [bp+8]          ; arguments
  518. y1    equ    [bp+12]
  519. z1    equ    [bp+16]
  520. x2    equ    [bp+20]
  521. y2    equ    [bp+24]
  522. z2    equ    [bp+28]
  523.  
  524.     PUBLIC    _big_dist
  525.  
  526. _big_dist    proc    far
  527.  
  528.     .386
  529.     push    ebp
  530.     mov    ebp,esp
  531.  
  532.     push    ecx
  533.  
  534.     mov     eax,x1
  535.     sub    eax,x2
  536.     cdq
  537.     xor    eax,edx
  538.     sub    eax,edx
  539.     mov    ecx,eax
  540.  
  541.     mov     eax,y1
  542.     sub    eax,y2
  543.     cdq
  544.     xor    eax,edx
  545.     sub    eax,edx
  546.     add    ecx,eax
  547.  
  548.     mov     eax,z1
  549.     sub    eax,z2
  550.     cdq
  551.     xor    eax,edx
  552.     sub    eax,edx
  553.     add    eax,ecx
  554.  
  555.     shld    edx,eax,16    ; return in eax and dx:ax
  556.  
  557.     pop    ecx
  558.  
  559.     mov    esp,ebp
  560.     pop    ebp
  561.     ret
  562.  
  563. _big_dist    endp
  564.  
  565.  
  566.  
  567.  
  568.     end
  569.  
  570.  
  571.