Cpr E 281x/282x Laboratory

Lab 10a

Continuing the Introduction to the CodeWarrior/PowerPC Platform

 

1. Objectives

 

In this lab you will become familiar with the assembly for the PowerPC.  Then you will convert the PCSpim introduction programs, which were written with MIPS instructions, to PowerPC instructions.

 

1.1           Reference files for Lab

 

Lab Evaluation Form

 

 

2. Prelab

 

Before you come to lab it will be useful to become familiar with the differences between the PowerPC and MIPS assembly instructions.  You can find information on the PowerPC in the manuals located in the lab, or for an online version click here.  Specific information for the instructions is in section 8.2.  You can also find some instructions in the quick reference: QuickrefPPC.html.

 

 

3. Setup

 

Create a lab10a folder in your 282x lab directory.  Follow the instructions for each part.

 

 

4. Assembly Language in Code Warrior

Step 1 - Create a new project 

Start up CodeWarrior.

Select File à New

On the window that appears click and select CprE282x - Power PC 555 Stationary

On the subsequent window, enter the project name “lab1” and set the location your *282x*/lab10a directory that you created for lab10a.

In the Select Project Stationary window, select Assembly Code (from C linkage) option. This is because we are going to deal with assembly programs. Selecting the "C code" option would enable us to code in C using CodeWarrior.

NOTE: By default, CodeWarrior saves projects with the extension ".mcp"

Now a new Project is created for you, and the main project window appears. Note on its toolbar that icons appear for actions like "Make" and "Run". On expanding the C + Assembly Source Files dropdown, you will notice 2 files: main.c and MainSource.asm

Main.c:

Study the C program in main1.c (by double clicking it, it opens). The JumpAsm( ) function in main( ) calls the assembly code. An assembly code subroutine is called by a branch and link statement: bl StartAsm.

MainSource.asm:

Next, take a look at the assembly code and comments in MainSource.asm.

Assembly Program to add 3 numbers

Download Lab1.asm to your project directory.  Once this is done the next important step is to add this file to your project. 

Delete the existing MainSource.asm file after you add Lab1.asm to your project.

Select "Project à Add files"

Select the downloaded "Lab1.asm" file and see the file appear on the project window. It should be added to the "Runtime" listing of files. You can also move it to the  "C+Assembly Source Files" section by dragging it.

Open Lab1.asm and observe the structure of the program, line by line, and the comments for each line. Use QuickrefPPC.html for short explanations on assembly language instructions.  This is just an introduction; you will study the PowerPC instruction set in more detail later.

Take note of which registers (named r#) are loaded with the 3 numbers to be added, and insert appropriate instructions to perform addition (a+b+c), placing the final sum in register r31.  (Perform this addition only using those 3 registers).

Running the program

Turn on the PowerBox via the switch on the back of the unit. 

From the CodeWarrior menu, select Project à Enable Debugger. Then select Project à Debug or press Ctrl+F5.  CodeWarrior will automatically attempt to compile, download and run the code.  If there are any syntax errors, the code will not be downloaded.  

Now you see that the blue arrow points at the start of main( ). This is the current program pointer. We can execute a program step by step (one instruction at a time) by making this arrow move one line after another.

To move forward in the code, select Debug à Step Over or press F10.  Recall that there are several commands for debugging:

It is handy to use F10 and F11  in debugging. Press F5 to run the program to completion. 

Setting Breakpoints

Press Project à Debug or Ctrl+F5 again to download the program.  Notice how the blue arrow denotes the current location of where you are at in the program. 

Press F9 to set a breakpoint on some line. Press F5 to run to the breakpoint.  Now, press F10 and watch the progress.  If you want to remove a breakpoint, simply press F9 on the same line.

Step-by-Step Debugging

Press Project à Debug or Ctrl+F5 again to download the program.  Now hit F10 once. The blue arrow now points at JumpAsm( ). Now the aim is to ENTER INTO THE FUNCTION JumpAsm( ) and proceed step by step. So hit F11 (Step Into) and notice that the pointer moves to the first line in JumpAsm( ). Hit F10 again to proceed until bl StartAsm (which transfers control to the assembly function we added in the other file). Now hit F11 and watch the control flow enter into the assembly code.

Watching Registers

This program adds 3 numbers – 10, 20 and 30 – and places the result in GPR31 (General Purpose Register). The data memory is declared outside the body as DataSeg. Select Window à Registers Window à GPR. Now you can see registers R0 to R31, the stack pointer SP, the pogram counter PC, and a few other general purpose registers. This window is very important for debugging. Registers get updated on every access and their pattern can be observed as we step through the code.

Now hit F10 repeatedly and watch the registers change. As we step through registers r31, r30 and r29, we can see that the respective values (from the data segment) are loaded into the registers one after another. Finally r31 stores the sum. At blr, the flow is transferred back to the calling code. 

 Report the final answer and your understanding of the code to the TA.

As time permits, continue to familiarize yourself with the CodeWarrior environment by exploring more options.

 

 

5. MIPS vs. PowerPC

 

Convert the three examples from lab 9a, the first PCSpim lab, to use PowerPC instructions.  Write the PowerPC instruction next to the MIPS instruction on the answer sheet.  Your new PowerPC program may need more than one instruction to complete its comparable MIPS instruction and vice versa.  Use the same registers used in the example programs whenever possible.  Read the notes provided at the beginning of each example.

 

Close down any open projects in CodeWarrior and create a new project called “lab10a_example1”.  You will replace the dummy add instruction in MainSource.asm with your code.  Step through each program in CodeWarrior and watch the registers window.  At the end of each program fill out the table of relevant register values for the final state of the registers.  This means that if a register is used in an instruction then the final value of that register will be recorded in the table.  Have the TA sign off on each example before continuing on to the next.

 

For each example create a new project as you did for example 1. 

 

The portion of the code from each example from lab 9a that you will need to use for this lab is given below.  (You do not need the main and end code that was there in lab 9).

 

 

Example 1:

 

Notes:

-          Some commands have a period at the end of them (i.e. andi.).

-          Instead of using $zero, use register R29 which you will set to zero using the instruction: andi. r29, r29, 0    # define zero value register.

-          Clear all registers that you will be using.  (i.e. at the beginning of the example program put addi r8, r29, 0 to clear register 8).

 

 # arithmetic instructions, calculate (4((6+2)-(1+2))/2)

 

 addi $16, $zero, 2     # 2

 addi $17, $zero, 6     # 6

 addi $18, $zero, 1     # 1

 add $19, $16, $17      # (6+2)=a

 add $20, $18, $16      # (1+2)=b

 sub $21, $19, $20      # (a)-(b)

 

 add $22, $16, $16      # 4

 mult $22, $21          # 4*(a-b)=c

 mflo $8                # move result (c) to R8

 

 div $8, $16            # c/2

 mflo $9                # move answer to R9

 

 

Example 2:

 

Notes:

-          The lui instruction can be handled with lis and ori instructions.

-          Do not use r13.

-          The starting address of the RAM is defined in the Defines.h.  Use this value and add 0xF000 for your base address for data.

-          To view the memory select Data à View Memory.  The memory window will appear.  Type the base address in and press enter.  Enter the final values, in the base address row of the memory window, into the table on the answer sheet.

 

 # data transfer and logical instructions

 

 # data values to load and store

 addi $9, $zero, 3      # set R9 value to 3

 addi $10, $zero, 12    # set R10 value to 12

 

 # value = address for data

 lui $8, 0x1000         # set R8 = 0x10000000

 

 sw $9, 0($8)           # store value from R9

 sw $10, 4($8)          # store value from R10

 

 addi $9, $zero, 0      # clear R9

 addi $10, $zero, 0     # clear R10

 

 lw $11, 0($8)          # load value to R11

 lw $12, 4($8)          # load value to R12

 

 or $13, $11, $12       # R11 | R12

 andi $14, $13, 15      # R13 & R9

 srl $16, $12, 2        # shift bits right by 2

 sll $16, $16, 1        # shift bits left by 1

 

 sw $16, 8($8)          # store value from R16

 

 

Example 3:

 

 

Notes:

-          Do not manipulate the stack pointer.

-          Rather than using a stack location to store the temporary data, use the same base address as you did for example 2.

-          Enter the final values, in the base address row of the memory window, into the table on the answer sheet.

 

 

 # C to Assembly translation and conditional branch

 

 # int i = 0;

 # int A[16];

 #

 # while(i <= 15)

 # {

 #    A[i] = i;

 # }

 

 

Loop:

 addi $6, $zero, 1      # set R6 to 1

 sw $8, 0($5)           # store R8 in stack

 addi $8, $8, 1         # increment value

 addi $5, $5, 4         # increment stack pointer

 slti $7, $8, 16        # set R7 to 1, else 0 

 beq $7, $6, Loop       # conditional branch