Понятие о сопроцессорах. FPU

  1. Сопроцессоры:
    • Сопроцессор 1 - FPU
    • Сопроцессор 0 - управления
  2. Стандарт IEEE 754
    • Mars -> Tools -> Floating Point Representation

  3. FPU MIPS
    1. MIPS поддерживает числа с плавающей точкой одинарной и двойной точности в IEEE-формате.
    2. Архитектура MIPS предусматривает наличие тридцати двух 32-битных регистров для чисел с плавающей точкой "$f0–$f31". Это не те же самые регистры, которые мы использовали до сих пор.
    3. Числа двойной точности (64-битные) размещаются в парах 32-битных регистров, так что для операций с такими числами доступны только 16 четных регистров "$f0, $f2, $f4, ..., $f30".
    4. В соответствии с соглашением, принятым в архитектуре MIPS, у этих регистров разное назначение:
      • Название

        Номер

        Назначение

        $fv0–$fv1

        0, 2

        Значение, возвращаемое функцией

        $ft0–$ft3

        4, 6, 8, 10

        Временные переменные

        $fa0–$fa1

        12, 14

        Аргументы функции

        $ft4–$ft5

        16, 18

        Временные переменные

        $fs0–$fs5

        20, 22, 24, 26, 28, 30

        Сохраняемые переменные

    5. Код операции у всех команд с плавающей точкой равен 17 (10001 2 ). Для определения типа команды в них должны присутствовать поля funct и cop (от англ. coprocessor). Ниже показан формат команд типа F, используемый для чисел с плавающей точкой.
      • op

        cop

        ft

        fs

        fd

        funct

        6bits

        5bits

        5bits

        5bits

        5bits

        6bits

      Поле cop равно 16 (10000 2 ) для команд одинарной точности и 17 (10001 2 ) для команд двойной точности. Аналогично командам типа R, у команд типа F есть два операнда-источника (fs и ft) и один операнд-назначение (fd). Формат команд типа F
    6. Команды одинарной и двойной точности различаются суффиксом в мнемонике (.s и .d соответственно). Команды с плавающей точкой включают сложение (add.s, add.d), вычитание (sub.s, sub.d), умножение (mul.s, mul.d), деление (div.s, div.d), изменение знака (neg.s, neg.d) и вычисление модуля (abs.s, abs.d).
    7. Регистры с плавающей точкой загружаются из памяти и записываются в память при помощи команд lwc1 и swc1 соответственно. Эти команды перемещают по 32 бита, так что для работы с числами двойной точности необходимо использовать по две такие команды.
    8. В тех случаях, когда ветвление зависит от условия, вычисляемого с использованием чисел с плавающей точкой, оно делится на две части. Сначала команда сравнения устанавливает или сбрасывает специальный флаг условия fpcond (от англ. floating point condition flag, флаг "0" "Coproc 1" в Mars). После этого команда ветвления проверяет этот флаг и в зависимости от его состояния осуществляет переход. Команды сравнения включают команды проверки на равенство (c.seq.s/c.seq.d), проверки на то, что один операнд меньше другого (c.lt.s/c.lt.d) или меньше или равен другому (c.le.s/c.le.d). Команды ветвления bc1f и bc1t осуществляют переход, если флаг fpcond имеет значение ЛОЖЬ или ИСТИНА соответственно. Другие варианты сравнений, такие как проверка на неравенство или на то, что один операнд больше другого, или больше или равен другому, осуществляются при помощи команд с суффиксами seq, lt, le и последующей командой bc1f.
  4. Пример. Использованы инструкции расширенного языка ассемблера.

   1 ## newton.asm -- compute sqrt(n) 
   2 
   3 ## given an approximation x to sqrt(n),
   4 ## an improved approximation is:
   5 
   6 ## x' = (1/2)(x + n/x)
   7 
   8 ## $f0  ---  n
   9 ## $f1  ---  1.0
  10 ## $f2  ---  2.0
  11 ## $f3  ---  x  : current approx.
  12 ## $f4  ---  x' : next approx.
  13 ## $f8  ---  temp
  14 
  15         .text
  16         .globl main
  17 
  18 main:   
  19 
  20         l.s     $f0,n               # get n
  21         l.s     $f1,con_1           # constant 1.0
  22         l.s     $f2,con_2           # constant 2.0
  23         l.s     $f3,con_1           # x == first approx.
  24         l.s     $f10,ep             # five figure accuracy
  25                 
  26 loop:   
  27         mov.s   $f4,$f0             # x' = n
  28         div.s   $f4,$f4,$f3         # x' = n/x
  29         add.s   $f4,$f3,$f4         # x' = x + n/x
  30         div.s   $f3,$f4,$f2         # x    = (1/2)(x + n/x)
  31 
  32         mul.s   $f8,$f3,$f3         # x^2
  33         div.s   $f8,$f0,$f8         # n/x^2
  34         sub.s   $f8,$f8,$f1         # n/x^2 - 1.0
  35         abs.s   $f8,$f8             # |n/x^2 - 1.0|
  36         c.lt.s  $f8,$f10            # |x^2 - n| < small ?
  37         bc1t    done                # yes: done
  38   
  39         j       loop                # next approximation
  40         
  41 done:
  42         mov.s   $f12,$f3            # print the result
  43         li      $v0,2
  44         syscall
  45  
  46         li      $a0,0
  47         li      $v0,10              # return to OS
  48         syscall
  49 ##
  50 ##  Data Segment  
  51 ##
  52         .data
  53 n:      .float  4.0
  54 ep:     .float  1.0e-5
  55 con_1:  .float  1.0
  56 con_2:  .float  2.0

ArchitectureAssembler2015/15_FPU_Coprocessors (последним исправлял пользователь FrBrGeorge 2024-06-17 12:51:44)